You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2013/02/08 19:29:51 UTC
[30/32] git commit: ISIS-327: done
ISIS-327: done
Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/ed11bc04
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/ed11bc04
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/ed11bc04
Branch: refs/heads/master
Commit: ed11bc0437b9fbca016324430446ccd4e4d9f7e6
Parents: 7b745ec
Author: Dan Haywood <da...@apache.org>
Authored: Fri Feb 8 17:52:28 2013 +0000
Committer: Dan Haywood <da...@apache.org>
Committed: Fri Feb 8 18:00:49 2013 +0000
----------------------------------------------------------------------
.../EventSerializerRendererContext.java | 6 +-
.../RestfulObjectsSpecEventSerializer.java | 24 ++-
core/pom.xml | 22 +-
.../system/session/IsisSessionFactoryAbstract.java | 125 +++++++++
...ssionFactoryAbstractTest_init_and_shutdown.java | 205 +++++++++++++++
.../src/main/webapp/WEB-INF/isis.properties | 3 +
6 files changed, 369 insertions(+), 16 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/isis/blob/ed11bc04/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/eventserializer/EventSerializerRendererContext.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/eventserializer/EventSerializerRendererContext.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/eventserializer/EventSerializerRendererContext.java
index 9cb2ee7..98b6711 100644
--- a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/eventserializer/EventSerializerRendererContext.java
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/eventserializer/EventSerializerRendererContext.java
@@ -12,15 +12,17 @@ import org.apache.isis.viewer.restfulobjects.rendering.RendererContext;
public class EventSerializerRendererContext implements RendererContext {
+ private final String baseUrl;
private final Where where;
- public EventSerializerRendererContext(Where where) {
+ public EventSerializerRendererContext(String baseUrl, Where where) {
+ this.baseUrl = baseUrl;
this.where = where;
}
@Override
public String urlFor(String url) {
- return "[base]/" + url;
+ return baseUrl + url;
}
@Override
http://git-wip-us.apache.org/repos/asf/isis/blob/ed11bc04/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/eventserializer/RestfulObjectsSpecEventSerializer.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/eventserializer/RestfulObjectsSpecEventSerializer.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/eventserializer/RestfulObjectsSpecEventSerializer.java
index 8a23976..29e1b14 100644
--- a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/eventserializer/RestfulObjectsSpecEventSerializer.java
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/eventserializer/RestfulObjectsSpecEventSerializer.java
@@ -1,6 +1,10 @@
package org.apache.isis.viewer.restfulobjects.rendering.eventserializer;
import java.io.IOException;
+import java.util.Map;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
import org.apache.isis.applib.annotation.Programmatic;
import org.apache.isis.applib.annotation.Where;
@@ -20,15 +24,29 @@ public class RestfulObjectsSpecEventSerializer implements EventSerializer {
private final static JsonMapper jsonMapper = JsonMapper.instance();
private final static DomainObjectReprRenderer.Factory objectRendererFactory = new DomainObjectReprRenderer.Factory();
-
+ private final static String BASE_URL_KEY = RestfulObjectsSpecEventSerializer.class.getName() + ".baseUrl";
+ private static final String BASE_URL_DEFAULT = "http://localhost:8080/restful/";
+
+ private String baseUrl;
+
+ @PostConstruct
+ public void init(Map<String,String> props) {
+ final String baseUrlFromConfig = props.get(BASE_URL_KEY);
+ baseUrl = baseUrlFromConfig != null? baseUrlFromConfig: BASE_URL_DEFAULT;
+ }
+
+ @PreDestroy
+ public void shutdown() {
+ }
+
@Programmatic
@Override
public Object serialize(EventMetadata metadata, EventPayload payload) {
- final RendererContext rendererContext = new EventSerializerRendererContext(Where.OBJECT_FORMS);
+ final RendererContext rendererContext = new EventSerializerRendererContext(baseUrl, Where.OBJECT_FORMS);
final JsonRepresentation payloadRepr = asPayloadRepr(rendererContext, payload);
final JsonRepresentation eventRepr = asEventRepr(metadata, payloadRepr);
-
+
return jsonFor(eventRepr);
}
http://git-wip-us.apache.org/repos/asf/isis/blob/ed11bc04/core/pom.xml
----------------------------------------------------------------------
diff --git a/core/pom.xml b/core/pom.xml
index e42e438..82b01aa 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -1261,17 +1261,7 @@ ${license.additional-notes}
</exclusion>
</exclusions>
</dependency>
- <dependency>
- <groupId>org.apache.geronimo.specs</groupId>
- <artifactId>geronimo-jsp_2.1_spec</artifactId>
- <version>1.0.1</version>
- </dependency>
- <dependency>
- <groupId>org.apache.geronimo.specs</groupId>
- <artifactId>geronimo-jta_1.1_spec</artifactId>
- <version>1.1.1</version>
- </dependency>
-
+
<dependency>
<groupId>org.htmlparser</groupId>
<artifactId>htmlparser</artifactId>
@@ -1338,6 +1328,16 @@ ${license.additional-notes}
<!-- Specs -->
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
+ <artifactId>geronimo-jsp_2.1_spec</artifactId>
+ <version>1.0.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.geronimo.specs</groupId>
+ <artifactId>geronimo-jta_1.1_spec</artifactId>
+ <version>1.1.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jta_1.0.1B_spec</artifactId>
<version>1.1.1</version>
</dependency>
http://git-wip-us.apache.org/repos/asf/isis/blob/ed11bc04/core/runtime/src/main/java/org/apache/isis/core/runtime/system/session/IsisSessionFactoryAbstract.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/session/IsisSessionFactoryAbstract.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/session/IsisSessionFactoryAbstract.java
index 26d3088..4915bb9 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/session/IsisSessionFactoryAbstract.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/session/IsisSessionFactoryAbstract.java
@@ -24,13 +24,20 @@ import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.CoreMatchers.nullValue;
+import java.lang.reflect.Method;
import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
import org.apache.isis.core.commons.authentication.AuthenticationSession;
import org.apache.isis.core.commons.components.ApplicationScopedComponent;
import org.apache.isis.core.commons.config.IsisConfiguration;
import org.apache.isis.core.commons.lang.JavaClassUtils;
import org.apache.isis.core.metamodel.adapter.oid.OidMarshaller;
+import org.apache.isis.core.metamodel.adapter.util.InvokeUtils;
import org.apache.isis.core.metamodel.spec.SpecificationLoaderSpi;
import org.apache.isis.core.runtime.authentication.AuthenticationManager;
import org.apache.isis.core.runtime.authorization.AuthorizationManager;
@@ -41,6 +48,7 @@ import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
import org.apache.isis.core.runtime.system.persistence.PersistenceSessionFactory;
import org.apache.isis.core.runtime.userprofile.UserProfile;
import org.apache.isis.core.runtime.userprofile.UserProfileLoader;
+import org.apache.log4j.Logger;
/**
* Creates an implementation of
@@ -57,6 +65,8 @@ import org.apache.isis.core.runtime.userprofile.UserProfileLoader;
*/
public abstract class IsisSessionFactoryAbstract implements IsisSessionFactory {
+ private final static Logger LOG = Logger.getLogger(IsisSessionFactoryAbstract.class);
+
private final DeploymentType deploymentType;
private final IsisConfiguration configuration;
private final TemplateImageLoader templateImageLoader;
@@ -91,8 +101,61 @@ public abstract class IsisSessionFactoryAbstract implements IsisSessionFactory {
this.persistenceSessionFactory = persistenceSessionFactory;
this.serviceList = serviceList;
this.oidMarshaller = oidMarshaller;
+
+ validateServices(serviceList);
+ }
+
+ /**
+ * Validate domain services lifecycle events.
+ *
+ * <p>
+ * Specifically:
+ * <ul>
+ * <li>All {@link PostConstruct} methods must either take no arguments or take a {@link Properties} object.</li>
+ * <li>All {@link PreDestroy} methods must take no arguments.</li>
+ * </ul>
+ *
+ * <p>
+ * If this isn't the case, then we fail fast.
+ */
+ private void validateServices(List<Object> serviceList) {
+ for (Object service : serviceList) {
+ final Method[] methods = service.getClass().getMethods();
+ for (Method method : methods) {
+ validatePostConstructMethods(service, method);
+ validatePreDestroyMethods(service, method);
+ }
+ }
}
+ private void validatePostConstructMethods(Object service, Method method) {
+ PostConstruct postConstruct = method.getAnnotation(PostConstruct.class);
+ if(postConstruct == null) {
+ return;
+ }
+ final int numParams = method.getParameterTypes().length;
+ if(numParams == 0) {
+ return;
+ }
+ if(numParams == 1 && method.getParameterTypes()[0].isAssignableFrom(Map.class)) {
+ return;
+ }
+ throw new IllegalStateException("Domain service " + service.getClass().getName() + " has @PostConstruct method " + method.getName() + "; such methods must take either no argument or 1 argument of type Map<String,String>");
+ }
+
+ private void validatePreDestroyMethods(Object service, Method method) {
+ PreDestroy preDestroy = method.getAnnotation(PreDestroy.class);
+ if(preDestroy == null) {
+ return;
+ }
+ final int numParams = method.getParameterTypes().length;
+ if(numParams == 0) {
+ return;
+ }
+ throw new IllegalStateException("Domain service " + service.getClass().getName() + " has @PreDestroy method " + method.getName() + "; such methods must take no arguments");
+ }
+
+
// ///////////////////////////////////////////
// init, shutdown
// ///////////////////////////////////////////
@@ -117,10 +180,16 @@ public abstract class IsisSessionFactoryAbstract implements IsisSessionFactory {
authenticationManager.init();
authorizationManager.init();
persistenceSessionFactory.init();
+
+ initServices(getConfiguration());
}
+
@Override
public void shutdown() {
+
+ shutdownServices();
+
persistenceSessionFactory.shutdown();
authenticationManager.shutdown();
specificationLoaderSpi.shutdown();
@@ -128,6 +197,62 @@ public abstract class IsisSessionFactoryAbstract implements IsisSessionFactory {
userProfileLoader.shutdown();
}
+ protected void initServices(IsisConfiguration configuration) {
+ final List<Object> services = getServices();
+ Map<String, String> props = configuration.asMap();
+ for (Object service : services) {
+ callPostConstructIfExists(service, props);
+ }
+ }
+
+ private void callPostConstructIfExists(Object service, Map<String, String> props) {
+ LOG.info("calling @PostConstruct on all domain services");
+ Method[] methods = service.getClass().getMethods();
+ for (Method method : methods) {
+ PostConstruct postConstruct = method.getAnnotation(PostConstruct.class);
+ if(postConstruct == null) {
+ continue;
+ }
+ LOG.info("calling @PostConstruct method: " + service.getClass().getName() + ": " + method.getName());
+
+ final int numParams = method.getParameterTypes().length;
+
+ // unlike shutdown, we don't swallow exceptions; would rather fail early
+ if(numParams == 0) {
+ InvokeUtils.invoke(method, service);
+ } else {
+ InvokeUtils.invoke(method, service, new Object[]{props});
+ }
+ }
+ }
+
+
+ protected void shutdownServices() {
+ final List<Object> services = getServices();
+ for (Object service : services) {
+ callPreDestroyIfExists(service);
+ }
+ }
+
+ private void callPreDestroyIfExists(Object service) {
+ LOG.info("calling @PreDestroy on all domain services");
+ final Method[] methods = service.getClass().getMethods();
+ for (Method method : methods) {
+ PreDestroy preDestroy = method.getAnnotation(PreDestroy.class);
+ if(preDestroy == null) {
+ continue;
+ }
+ LOG.info("calling @PreDestroy method: " + service.getClass().getName() + ": " + method.getName());
+ try {
+ InvokeUtils.invoke(method, service);
+ } catch(Exception ex) {
+ // do nothing
+ LOG.warn("@PreDestroy method threw exception - continuing anyway", ex);
+ }
+ }
+ }
+
+
@Override
public IsisSession openSession(final AuthenticationSession authenticationSession) {
final PersistenceSession persistenceSession = persistenceSessionFactory.createPersistenceSession();
http://git-wip-us.apache.org/repos/asf/isis/blob/ed11bc04/core/runtime/src/test/java/org/apache/isis/core/runtime/system/session/IsisSessionFactoryAbstractTest_init_and_shutdown.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/test/java/org/apache/isis/core/runtime/system/session/IsisSessionFactoryAbstractTest_init_and_shutdown.java b/core/runtime/src/test/java/org/apache/isis/core/runtime/system/session/IsisSessionFactoryAbstractTest_init_and_shutdown.java
new file mode 100644
index 0000000..bf8a186
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/isis/core/runtime/system/session/IsisSessionFactoryAbstractTest_init_and_shutdown.java
@@ -0,0 +1,205 @@
+package org.apache.isis.core.runtime.system.session;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.assertThat;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.annotation.PostConstruct;
+
+import org.apache.isis.core.commons.config.IsisConfiguration;
+import org.apache.isis.core.commons.config.IsisConfigurationDefault;
+import org.apache.isis.core.metamodel.adapter.oid.OidMarshaller;
+import org.apache.isis.core.metamodel.spec.SpecificationLoaderSpi;
+import org.apache.isis.core.runtime.authentication.AuthenticationManager;
+import org.apache.isis.core.runtime.authorization.AuthorizationManager;
+import org.apache.isis.core.runtime.imageloader.TemplateImageLoader;
+import org.apache.isis.core.runtime.system.DeploymentType;
+import org.apache.isis.core.runtime.system.persistence.PersistenceSessionFactory;
+import org.apache.isis.core.runtime.userprofile.UserProfileLoader;
+import org.apache.isis.core.unittestsupport.jmock.auto.Mock;
+import org.apache.isis.core.unittestsupport.jmocking.JUnitRuleMockery2;
+import org.apache.isis.core.unittestsupport.jmocking.JUnitRuleMockery2.Mode;
+import org.hamcrest.CoreMatchers;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import com.google.common.collect.Lists;
+
+public class IsisSessionFactoryAbstractTest_init_and_shutdown {
+
+ public static class DomainServiceWithNoPostConstructOrPreDestroy {
+ }
+
+ public static class DomainServiceWithValidPostConstructNoParams {
+ boolean called = false;
+ @PostConstruct
+ public void postConstruct() {
+ called = true;
+ }
+ }
+
+ public static class DomainServiceWithValidPostConstructPropertiesParam {
+ boolean called = false;
+ Map<String, String> props;
+ @PostConstruct
+ public void postConstruct(Map<String,String> props) {
+ this.props = props;
+ called = true;
+ }
+ }
+
+ public static class DomainServiceWithValidPostConstructSubtypeOfPropertiesParam {
+ boolean called = false;
+ Object props;
+ @PostConstruct
+ public void postConstruct(Object props) {
+ this.props = props;
+ called = true;
+ }
+ }
+
+ public static class DomainServiceWithInvalidPostConstructWrongNumberParams {
+ @PostConstruct
+ public void postConstruct(int i, Properties props) {}
+ }
+
+ public static class DomainServiceWithInvalidPostConstructWrongTypeOfParam {
+ @PostConstruct
+ public void postConstruct(int i) {}
+ }
+
+ public static class DomainServiceWithValidPreDestroyNoParams {
+ boolean called = false;
+ @PostConstruct
+ public void postConstruct() {
+ called = true;
+ }
+ }
+
+ public static class DomainServiceWithInvalidPreDestroyWrongNumberParams {
+ @PostConstruct
+ public void postConstruct(int i) {}
+ }
+
+
+
+ @Rule
+ public JUnitRuleMockery2 context = JUnitRuleMockery2.createFor(Mode.INTERFACES_AND_CLASSES);
+
+ @Mock
+ private DeploymentType deploymentType;
+ @Mock
+ private SpecificationLoaderSpi specificationLoader;
+ @Mock
+ private TemplateImageLoader templateImageLoader;
+ @Mock
+ private AuthenticationManager authenticationManager;
+ @Mock
+ private AuthorizationManager authorizationManager;
+ @Mock
+ private UserProfileLoader userProfileLoader;
+ @Mock
+ private PersistenceSessionFactory persistenceSessionFactory;
+ @Mock
+ private OidMarshaller oidMarshaller;
+
+ private IsisConfigurationDefault configuration;
+ private List<Object> serviceList;
+
+ private IsisSessionFactoryAbstract isfa;
+
+
+ @Before
+ public void setUp() throws Exception {
+ configuration = new IsisConfigurationDefault();
+ configuration.add("foo", "bar");
+
+ serviceList = Lists.newArrayList();
+ context.ignoring(deploymentType, specificationLoader, templateImageLoader, authenticationManager, authorizationManager, userProfileLoader, persistenceSessionFactory, oidMarshaller);
+ }
+
+ @Test
+ public void emptyListOfServices() {
+ isfa = createIsisSessionFactoryAbstract(serviceList);
+ }
+
+ @Test
+ public void preConstruct_DomainServiceWithNoPostConstructOrPreDestroy() {
+ serviceList.add(new DomainServiceWithNoPostConstructOrPreDestroy());
+ isfa = createIsisSessionFactoryAbstract(serviceList);
+
+ isfa.init();
+ isfa.shutdown();
+ }
+
+ @Test
+ public void preConstruct_DomainServiceWithValidPostConstructNoParams() {
+ DomainServiceWithValidPostConstructNoParams domainService = new DomainServiceWithValidPostConstructNoParams();
+ serviceList.add(domainService);
+ isfa = createIsisSessionFactoryAbstract(serviceList);
+ isfa.init();
+ assertThat(domainService.called,is(true));
+ isfa.shutdown();
+ }
+
+ @Test
+ public void preConstruct_DomainServiceWithValidPostConstructPropertiesParam() {
+ DomainServiceWithValidPostConstructPropertiesParam domainService = new DomainServiceWithValidPostConstructPropertiesParam();
+ serviceList.add(domainService);
+ isfa = createIsisSessionFactoryAbstract(serviceList);
+ isfa.init();
+ assertThat(domainService.called,is(true));
+ assertThat(domainService.props.get("foo"), is("bar"));
+ isfa.shutdown();
+ }
+
+ @Test
+ public void preConstruct_DomainServiceWithValidPostConstructSubtypeOfPropertiesParam() {
+ DomainServiceWithValidPostConstructSubtypeOfPropertiesParam domainService = new DomainServiceWithValidPostConstructSubtypeOfPropertiesParam();
+ serviceList.add(domainService);
+ isfa = createIsisSessionFactoryAbstract(serviceList);
+ isfa.init();
+ assertThat(domainService.called,is(true));
+ assertThat(domainService.props, is(not(nullValue())));
+ isfa.shutdown();
+ }
+
+ @Test(expected=IllegalStateException.class)
+ public void preConstruct_DomainServiceWithInvalidPostConstructWrongNumberParams() {
+ serviceList.add(new DomainServiceWithInvalidPostConstructWrongNumberParams());
+ isfa = createIsisSessionFactoryAbstract(serviceList);
+ }
+
+ @Test(expected=IllegalStateException.class)
+ public void preConstruct_DomainServiceWithInvalidPostConstructWrongTypeOfParam() {
+ serviceList.add(new DomainServiceWithInvalidPostConstructWrongTypeOfParam());
+ isfa = createIsisSessionFactoryAbstract(serviceList);
+ }
+
+ @Test
+ public void preConstruct_DomainServiceWithValidPreDestroyNoParams() {
+ DomainServiceWithValidPreDestroyNoParams domainService = new DomainServiceWithValidPreDestroyNoParams();
+ serviceList.add(domainService);
+ isfa = createIsisSessionFactoryAbstract(serviceList);
+ isfa.init();
+ assertThat(domainService.called,is(true));
+ isfa.shutdown();
+ }
+
+ @Test(expected=IllegalStateException.class)
+ public void preConstruct_DomainServiceWithInvalidPreDestroyWrongNumberParams() {
+ serviceList.add(new DomainServiceWithInvalidPreDestroyWrongNumberParams());
+ isfa = createIsisSessionFactoryAbstract(serviceList);
+ }
+
+
+ private IsisSessionFactoryAbstract createIsisSessionFactoryAbstract(List<Object> serviceList) {
+ return new IsisSessionFactoryAbstract(deploymentType, configuration, specificationLoader, templateImageLoader, authenticationManager, authorizationManager, userProfileLoader, persistenceSessionFactory, serviceList, oidMarshaller) {
+ };
+ }
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/ed11bc04/example/application/quickstart_wicket_restful_jdo/viewer-webapp/src/main/webapp/WEB-INF/isis.properties
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/viewer-webapp/src/main/webapp/WEB-INF/isis.properties b/example/application/quickstart_wicket_restful_jdo/viewer-webapp/src/main/webapp/WEB-INF/isis.properties
index 757952d..741a7c4 100644
--- a/example/application/quickstart_wicket_restful_jdo/viewer-webapp/src/main/webapp/WEB-INF/isis.properties
+++ b/example/application/quickstart_wicket_restful_jdo/viewer-webapp/src/main/webapp/WEB-INF/isis.properties
@@ -175,3 +175,6 @@ isis.services = objstore.jdo.todo.ToDoItemsJdo,\
#isis.fixtures.prefix=
#isis.fixtures=
+
+org.apache.isis.viewer.restfulobjects.rendering.eventserializer.RestfulObjectsSpecEventSerializer.baseUrl=http://localhost:8080/restful/
+