You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by ah...@apache.org on 2018/12/20 23:35:28 UTC
[isis] branch 2033-IoC updated: ISIS-2033: fixes
ServiceRegistry#validate
This is an automated email from the ASF dual-hosted git repository.
ahuber pushed a commit to branch 2033-IoC
in repository https://gitbox.apache.org/repos/asf/isis.git
The following commit(s) were added to refs/heads/2033-IoC by this push:
new 1ac707d ISIS-2033: fixes ServiceRegistry#validate
1ac707d is described below
commit 1ac707d4b5b9df9cbddedf3ffa09de2321b9c6c8
Author: Andi Huber <ah...@apache.org>
AuthorDate: Fri Dec 21 00:35:22 2018 +0100
ISIS-2033: fixes ServiceRegistry#validate
by properly iterating over discovered beans
also simplify weld testing with a BeanListBuilder
Task-Url: https://issues.apache.org/jira/browse/ISIS-2033
---
.../applib/services/registry/ServiceRegistry.java | 4 +
.../org/apache/isis/config/IsisConfiguration.java | 3 +
.../services/registry/ServiceRegistryDefault.java | 81 +++++++++++---
.../isis/core/metamodel/BeansForTesting.java | 121 +++++++++++++++++++++
.../services/ServicesInjectorDefaultTest.java | 30 ++---
.../ServicesInjectorDefaultTest_usingFields.java | 31 ++----
...rvicesInjectorDefaultTest_validateServices.java | 79 +++++---------
...InjectorDefaultTest_validateServices_happy.java | 68 ++++++++++++
8 files changed, 312 insertions(+), 105 deletions(-)
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/registry/ServiceRegistry.java b/core/applib/src/main/java/org/apache/isis/applib/services/registry/ServiceRegistry.java
index 7394627..4689998 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/registry/ServiceRegistry.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/registry/ServiceRegistry.java
@@ -122,6 +122,10 @@ public interface ServiceRegistry {
*/
boolean isRegisteredServiceInstance(Object pojo);
+ /**
+ * Verify domain service Ids are unique.
+ * @throws IllegalStateException - if validation fails
+ */
void validateServices();
diff --git a/core/config/src/main/java/org/apache/isis/config/IsisConfiguration.java b/core/config/src/main/java/org/apache/isis/config/IsisConfiguration.java
index a20e87c..e9980be 100644
--- a/core/config/src/main/java/org/apache/isis/config/IsisConfiguration.java
+++ b/core/config/src/main/java/org/apache/isis/config/IsisConfiguration.java
@@ -25,6 +25,8 @@ import java.util.Iterator;
import java.util.Map;
import java.util.stream.Stream;
+import javax.enterprise.context.ApplicationScoped;
+
import org.apache.isis.applib.AppManifest;
import org.apache.isis.applib.Module;
import org.apache.isis.applib.PropertyResource;
@@ -50,6 +52,7 @@ import static org.apache.isis.config.internal._Config.getConfiguration;
* Thus the {@link IsisConfiguration} held by different components may vary, but
* with each being a possible superset of the previous.
*/
+@ApplicationScoped
public interface IsisConfiguration {
/**
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/registry/ServiceRegistryDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/registry/ServiceRegistryDefault.java
index fd4c78e..b6a76a4 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/registry/ServiceRegistryDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/registry/ServiceRegistryDefault.java
@@ -19,6 +19,7 @@
package org.apache.isis.core.metamodel.services.registry;
+import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -34,14 +35,20 @@ import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.util.AnnotationLiteral;
+import org.apache.isis.applib.annotation.DomainService;
import org.apache.isis.applib.services.registry.ServiceRegistry;
import org.apache.isis.commons.internal.base._Casts;
import org.apache.isis.commons.internal.base._Lazy;
+import org.apache.isis.commons.internal.base._Strings;
import org.apache.isis.commons.internal.cdi._CDI;
import org.apache.isis.commons.internal.collections._Maps;
import org.apache.isis.commons.internal.collections._Multimaps;
+import org.apache.isis.commons.internal.collections._Multimaps.ListMultimap;
import org.apache.isis.commons.internal.collections._Multimaps.SetMultimap;
import org.apache.isis.commons.internal.collections._Sets;
+import org.apache.isis.core.metamodel.services.ServiceUtil;
+
+import static org.apache.isis.commons.internal.base._NullSafe.stream;
import lombok.val;
@@ -72,6 +79,7 @@ public final class ServiceRegistryDefault implements ServiceRegistry {
@Override
public Stream<Object> streamServices() {
+
if(registeredServiceInstances.isEmpty()) {
BeanManager beanManager = _CDI.getBeanManager();
@@ -80,9 +88,14 @@ public final class ServiceRegistryDefault implements ServiceRegistry {
for (Bean<?> bean : beans) {
val type = bean.getBeanClass();
+ val debug = type.getName().startsWith("org.apache.isis.");
- if(bean.getBeanClass().getName().startsWith("org.apache.isis.")) {
+ if(debug) {
System.out.println("!!! " + bean);
+ }
+
+ if(!isSingleton(type)) {
+ continue;
}
Optional<?> managedObject =
@@ -91,11 +104,14 @@ public final class ServiceRegistryDefault implements ServiceRegistry {
if(managedObject.isPresent()) {
registeredServiceInstances.add(managedObject.get());
- System.out.println("\t registering: " + managedObject.get());
+ if(debug) {
+ System.out.println("!!!\t registering: " + managedObject.get());
+ }
} else {
- if(bean.getBeanClass().getName().startsWith("org.apache.isis.")) {
- System.out.println("\t !!! bean not present: " + type.getName());
+
+ if(debug) {
+ System.out.println("!!!\t bean not present: " + type.getName());
}
}
@@ -132,24 +148,59 @@ public final class ServiceRegistryDefault implements ServiceRegistry {
@Override
public void validateServices() {
- // TODO Auto-generated method stub
-
+ validate(streamServices());
}
-
+
// -- HELPER ...
private final static AnnotationLiteral<Any> QUALIFIER_ANY =
new AnnotationLiteral<Any>() {
private static final long serialVersionUID = 1L;};
+
+ private boolean isSingleton(Class<?> cls) {
+
+ if(cls.isAnnotationPresent(Singleton.class) ||
+ cls.isAnnotationPresent(DomainService.class)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ // -- VALIDATE
+
+ private static void validate(final Stream<Object> serviceInstances) {
+
+ final ListMultimap<String, Object> servicesById = _Multimaps.newListMultimap();
+ serviceInstances.forEach(serviceInstance->{
+ String id = ServiceUtil.idOfPojo(serviceInstance);
+ System.out.println("!!! id="+id);
+
+ servicesById.putElement(id, serviceInstance);
+ });
+
+ final String errorMsg = servicesById.entrySet().stream()
+ .filter(entry->entry.getValue().size()>1) // filter for duplicates
+ .map(entry->{
+ String serviceId = entry.getKey();
+ List<Object> duplicateServiceEntries = entry.getValue();
+ return String.format("serviceId '%s' is declared by domain services %s",
+ serviceId, classNamesFor(duplicateServiceEntries));
+ })
+ .collect(Collectors.joining(", "));
+
+ if(_Strings.isNotEmpty(errorMsg)) {
+ throw new IllegalStateException("Service ids must be unique! "+errorMsg);
+ }
+ }
-
-// private final static AnnotationLiteral<Singleton> SINGLETON =
-// new AnnotationLiteral<Singleton>() {
-// private static final long serialVersionUID = 1L;};
-//
-// private final static AnnotationLiteral<ApplicationScoped> APPLICATIONSCOPED =
-// new AnnotationLiteral<ApplicationScoped>() {
-// private static final long serialVersionUID = 1L;};
+ private static String classNamesFor(Collection<Object> services) {
+ return stream(services)
+ .map(Object::getClass)
+ .map(Class::getName)
+ .collect(Collectors.joining(", "));
+ }
+
// -- LOOKUP SERVICE(S)
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/BeansForTesting.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/BeansForTesting.java
new file mode 100644
index 0000000..f5de3f7
--- /dev/null
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/BeansForTesting.java
@@ -0,0 +1,121 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.isis.core.metamodel;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.enterprise.inject.Produces;
+
+import org.mockito.Mockito;
+
+import org.apache.isis.applib.services.repository.RepositoryService;
+import org.apache.isis.commons.internal._Constants;
+import org.apache.isis.config.IsisConfiguration;
+import org.apache.isis.config.builder.IsisConfigurationBuilder;
+import org.apache.isis.core.metamodel.services.ServiceInjectorDefault;
+import org.apache.isis.core.metamodel.services.registry.ServiceRegistryDefault;
+import org.apache.isis.core.metamodel.specloader.InjectorMethodEvaluatorDefault;
+
+import static org.apache.isis.commons.internal.base._NullSafe.stream;
+
+/**
+ *
+ * @since 2.0.0-M2
+ *
+ */
+public final class BeansForTesting {
+
+ // -- BUILDER
+
+ public static BeanListBuilder builder() {
+ return new BeanListBuilder();
+ }
+
+ public static class BeanListBuilder {
+
+ private final Set<Class<?>> beans = new HashSet<>();
+
+ public Class<?>[] build() {
+ return beans.toArray(_Constants.emptyClasses);
+ }
+
+ public BeanListBuilder add(Class<?> bean) {
+ beans.add(bean);
+ return this;
+ }
+
+ public BeanListBuilder addAll(Class<?> ... beans) {
+ stream(beans)
+ .forEach(this.beans::add);
+ return this;
+ }
+
+ /**
+ * Adds IsisConfiguration support.
+ */
+ public BeanListBuilder config() {
+ beans.add(config);
+ return this;
+ }
+
+ /**
+ * Adds ServiceRegistry and ServiceInjector support.
+ */
+ public BeanListBuilder injector() {
+
+ addAll(
+ config,
+ InjectorMethodEvaluatorDefault.class,
+ ServiceRegistryDefault.class,
+ ServiceInjectorDefault.class);
+
+ return this;
+ }
+
+
+ }
+
+
+ // -- PREDEFINED
+
+ public static Class<?> config = _Config.class;
+ public static Class<?> mock_repository = _Mock_RepositoryService.class;
+
+ static class _Config {
+
+ @Produces
+ IsisConfiguration getConfiguration() {
+ return IsisConfigurationBuilder.getDefaultForUnitTesting()
+ .build();
+ }
+
+ }
+
+ static class _Mock_RepositoryService {
+
+ @Produces
+ RepositoryService mockRepositoryService() {
+ return Mockito.mock(RepositoryService.class);
+ }
+
+ }
+
+
+}
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefaultTest.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefaultTest.java
index 92e5744..3ecd870 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefaultTest.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefaultTest.java
@@ -43,10 +43,7 @@ import org.mockito.Mockito;
import org.apache.isis.applib.services.inject.ServiceInjector;
import org.apache.isis.applib.services.registry.ServiceRegistry;
import org.apache.isis.applib.services.repository.RepositoryService;
-import org.apache.isis.config.IsisConfiguration;
-import org.apache.isis.config.builder.IsisConfigurationBuilder;
-import org.apache.isis.core.metamodel.services.registry.ServiceRegistryDefault;
-import org.apache.isis.core.metamodel.specloader.InjectorMethodEvaluatorDefault;
+import org.apache.isis.core.metamodel.BeansForTesting;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.times;
@@ -56,13 +53,7 @@ import static org.mockito.Mockito.verify;
@EnableWeld
class ServicesInjectorDefaultTest {
- static class FactoriesForTesting {
-
- @Produces
- IsisConfiguration getConfiguration() {
- return IsisConfigurationBuilder.getDefaultForUnitTesting()
- .build();
- }
+ static class Mocks {
@Produces
SomeDomainObject mockDomainObject() {
@@ -93,16 +84,15 @@ class ServicesInjectorDefaultTest {
@WeldSetup
public WeldInitiator weld = WeldInitiator.from(
- FactoriesForTesting.class,
- IsisConfiguration.class,
- InjectorMethodEvaluatorDefault.class,
- ServiceRegistryDefault.class,
- ServiceInjectorDefault.class,
-
- RepositoryService.class,
- Service1.class,
- Service2.class
+ BeansForTesting.builder()
+ .injector()
+ .addAll(
+ Mocks.class,
+ Service1.class,
+ Service2.class
+ )
+ .build()
)
.build();
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefaultTest_usingFields.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefaultTest_usingFields.java
index ea3f9c7..7c9fd9d 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefaultTest_usingFields.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefaultTest_usingFields.java
@@ -30,10 +30,7 @@ import org.mockito.Mockito;
import org.apache.isis.applib.services.inject.ServiceInjector;
import org.apache.isis.applib.services.repository.RepositoryService;
-import org.apache.isis.config.IsisConfiguration;
-import org.apache.isis.config.builder.IsisConfigurationBuilder;
-import org.apache.isis.core.metamodel.services.registry.ServiceRegistryDefault;
-import org.apache.isis.core.metamodel.specloader.InjectorMethodEvaluatorDefault;
+import org.apache.isis.core.metamodel.BeansForTesting;
import static org.hamcrest.Matchers.any;
import static org.junit.Assert.assertThat;
@@ -44,13 +41,7 @@ import lombok.Getter;
class ServicesInjectorDefaultTest_usingFields {
- static class FactoriesForTesting {
-
- @Produces
- IsisConfiguration getConfiguration() {
- return IsisConfigurationBuilder.getDefaultForUnitTesting()
- .build();
- }
+ static class Mocks {
@Produces
RepositoryService mockRepositoryService() {
@@ -61,14 +52,16 @@ class ServicesInjectorDefaultTest_usingFields {
@WeldSetup
public WeldInitiator weld = WeldInitiator.from(
- FactoriesForTesting.class,
- InjectorMethodEvaluatorDefault.class,
- ServiceRegistryDefault.class,
- ServiceInjectorDefault.class,
- A.class,
- B.class,
- C.class
+ BeansForTesting.builder()
+ .injector()
+ .addAll(
+ Mocks.class,
+ A.class,
+ B.class,
+ C.class
+ )
+ .build()
)
.build();
@@ -100,7 +93,7 @@ class ServicesInjectorDefaultTest_usingFields {
@Inject @Getter private C someC;
}
- // not-managed managed
+ // not-managed
static class D {
@Inject @Getter private A someA;
@Inject @Getter private B someB;
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefaultTest_validateServices.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefaultTest_validateServices.java
index 2210999..4f86923 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefaultTest_validateServices.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefaultTest_validateServices.java
@@ -19,75 +19,52 @@
package org.apache.isis.core.metamodel.services;
-import java.util.List;
+import javax.inject.Inject;
-import org.junit.Before;
-import org.junit.Test;
+import org.jboss.weld.junit5.EnableWeld;
+import org.jboss.weld.junit5.WeldInitiator;
+import org.jboss.weld.junit5.WeldSetup;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.apache.isis.applib.annotation.DomainService;
import org.apache.isis.applib.services.registry.ServiceRegistry;
-import org.apache.isis.commons.internal.collections._Lists;
-import org.apache.isis.core.metamodel.services.registry.ServiceRegistryDefault;
+import org.apache.isis.core.metamodel.BeansForTesting;
-public class ServicesInjectorDefaultTest_validateServices {
+@EnableWeld
+class ServicesInjectorDefaultTest_validateServices {
- ServiceRegistry serviceRegistry;
+ // -- SCENARIO
+ @DomainService
public static class DomainServiceWithSomeId {
public String getId() { return "someId"; }
}
+ @DomainService
public static class DomainServiceWithDuplicateId {
public String getId() { return "someId"; }
}
- public static class DomainServiceWithDifferentId {
- public String getId() { return "otherId"; }
- }
-
- public static class ValidateServicesTestValidateServices extends ServicesInjectorDefaultTest_validateServices {
-
- List<Object> serviceList;
-
- @Before
- public void setUp() throws Exception {
- serviceList = _Lists.newArrayList();
- }
+ // --
- @Test(expected=IllegalStateException.class)
- public void validate_DomainServicesWithDuplicateIds() {
+ @WeldSetup
+ public WeldInitiator weld = WeldInitiator.from(
- // given
- serviceList.add(new DomainServiceWithSomeId());
- serviceList.add(new DomainServiceWithDuplicateId());
-
- serviceRegistry = new ServiceRegistryDefault();
- serviceList.forEach(serviceRegistry::registerServiceInstance);
-
-// serviceRegistry.registerServiceInstance(serviceInstance);
-// ServiceRegistryBuilder_forTesting.get()
-// .addServices(serviceList)
-// .build();
+ BeansForTesting.builder()
+ .injector()
+ .add(DomainServiceWithSomeId.class)
+ .add(DomainServiceWithDuplicateId.class)
+ .build()
- // when
- serviceRegistry.validateServices();
- }
+ )
+ .build();
- public void validate_DomainServicesWithDifferentIds() {
-
- // given
- serviceList.add(new DomainServiceWithSomeId());
- serviceList.add(new DomainServiceWithDifferentId());
-
- serviceRegistry = new ServiceRegistryDefault();
- serviceList.forEach(serviceRegistry::registerServiceInstance);
-
-// serviceRegistry = ServiceRegistryBuilder_forTesting.get()
-// .addServices(serviceList)
-// .build();
-
- // when
- serviceRegistry.validateServices();
- }
+ @Inject private ServiceRegistry serviceRegistry;
+ @Test
+ public void validate_DomainServicesWithDuplicateIds() {
+ Assertions.assertThrows(IllegalStateException.class, serviceRegistry::validateServices);
}
+
}
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefaultTest_validateServices_happy.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefaultTest_validateServices_happy.java
new file mode 100644
index 0000000..9a562dc
--- /dev/null
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefaultTest_validateServices_happy.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.isis.core.metamodel.services;
+
+import javax.inject.Inject;
+
+import org.jboss.weld.junit5.EnableWeld;
+import org.jboss.weld.junit5.WeldInitiator;
+import org.jboss.weld.junit5.WeldSetup;
+import org.junit.jupiter.api.Test;
+
+import org.apache.isis.applib.annotation.DomainService;
+import org.apache.isis.applib.services.registry.ServiceRegistry;
+import org.apache.isis.core.metamodel.BeansForTesting;
+
+@EnableWeld
+class ServicesInjectorDefaultTest_validateServices_happy {
+
+ // -- SCENARIO
+
+ @DomainService
+ public static class DomainServiceWithSomeId {
+ public String getId() { return "someId"; }
+ }
+
+ @DomainService
+ public static class DomainServiceWithDifferentId {
+ public String getId() { return "otherId"; }
+ }
+
+ @WeldSetup
+ public WeldInitiator weld = WeldInitiator.from(
+
+ BeansForTesting.builder()
+ .injector()
+ .add(DomainServiceWithSomeId.class)
+ .add(DomainServiceWithDifferentId.class)
+ .build()
+
+ )
+ .build();
+
+ @Inject private ServiceRegistry serviceRegistry;
+
+ @Test
+ public void validate_DomainServicesWithoutDuplicateIds() {
+ serviceRegistry.validateServices();
+ }
+
+
+}