Repository: polygene-java Updated Branches: refs/heads/develop d235b6385 -> 0cf199bc0
Better reporting on bad Composition during model creation. Project: http://git-wip-us.apache.org/repos/asf/polygene-java/repo Commit: http://git-wip-us.apache.org/repos/asf/polygene-java/commit/96de0124 Tree: http://git-wip-us.apache.org/repos/asf/polygene-java/tree/96de0124 Diff: http://git-wip-us.apache.org/repos/asf/polygene-java/diff/96de0124 Branch: refs/heads/develop Commit: 96de01240b1eabe0a22348623dbcca58b96567b2 Parents: c48230e Author: niclas <[email protected]> Authored: Thu Mar 30 09:01:37 2017 +0800 Committer: niclas <[email protected]> Committed: Thu Mar 30 09:01:37 2017 +0800 ---------------------------------------------------------------------- .../org/apache/polygene/api/PolygeneAPI.java | 33 +- .../composite/InvalidCompositeException.java | 102 +++++- .../bootstrap/AssemblyResportException.java | 60 ++++ .../bootstrap/ConfigurationAssembly.java | 30 -- .../apache/polygene/bootstrap/Energy4Java.java | 18 +- .../polygene/bootstrap/ModuleAssembly.java | 4 +- .../bootstrap/CompositeAssemblyImpl.java | 338 ++++++++++--------- .../bootstrap/ConfigurationAssemblyImpl.java | 45 --- .../runtime/composite/CompositeModel.java | 66 ++-- .../runtime/composite/ConstructorsModel.java | 4 +- .../TypedModifierInvocationHandler.java | 6 +- .../polygene/bootstrap/ErrorReportingTest.java | 84 +++++ .../polygene/test/AbstractPolygeneBaseTest.java | 20 +- .../polygene/library/rest/admin/RestTest.java | 2 +- 14 files changed, 495 insertions(+), 317 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/polygene-java/blob/96de0124/core/api/src/main/java/org/apache/polygene/api/PolygeneAPI.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/apache/polygene/api/PolygeneAPI.java b/core/api/src/main/java/org/apache/polygene/api/PolygeneAPI.java index ae03999..3b2f46d 100644 --- a/core/api/src/main/java/org/apache/polygene/api/PolygeneAPI.java +++ b/core/api/src/main/java/org/apache/polygene/api/PolygeneAPI.java @@ -140,30 +140,6 @@ public interface PolygeneAPI AssociationDescriptor associationDescriptorFor( AbstractAssociation association ); /** - * Function that returns the CompositeDescriptor of a Composite. - */ - Function<Composite, CompositeDescriptor> FUNCTION_DESCRIPTOR_FOR = composite -> { - if( composite instanceof Proxy ) - { - InvocationHandler invocationHandler = Proxy.getInvocationHandler( composite ); - return ( (CompositeInstance) invocationHandler ).descriptor(); - } - try - { - Class<? extends Composite> compositeClass = composite.getClass(); - Field instanceField = compositeClass.getField( "_instance" ); - Object instance = instanceField.get( composite ); - return ( (CompositeInstance) instance ).descriptor(); - } - catch( Exception e ) - { - InvalidCompositeException exception = new InvalidCompositeException( "Could not get _instance field" ); - exception.initCause( e ); - throw exception; - } - }; - - /** * Function that returns the CompositeInstance of a Composite. */ Function<Composite, CompositeInstance> FUNCTION_COMPOSITE_INSTANCE_OF = composite -> { @@ -180,9 +156,12 @@ public interface PolygeneAPI } catch( Exception e ) { - InvalidCompositeException exception = new InvalidCompositeException( "Could not get _instance field" ); - exception.initCause( e ); - throw exception; + throw new InternalError( "Could not get _instance field. This field should have been automatically generated by the Polygene runtime.", e ); } }; + + /** + * Function that returns the CompositeDescriptor of a Composite. + */ + Function<Composite, CompositeDescriptor> FUNCTION_DESCRIPTOR_FOR = FUNCTION_COMPOSITE_INSTANCE_OF.andThen( CompositeInstance::descriptor ); } http://git-wip-us.apache.org/repos/asf/polygene-java/blob/96de0124/core/api/src/main/java/org/apache/polygene/api/composite/InvalidCompositeException.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/apache/polygene/api/composite/InvalidCompositeException.java b/core/api/src/main/java/org/apache/polygene/api/composite/InvalidCompositeException.java index d9de0c7..4f8b3e3 100644 --- a/core/api/src/main/java/org/apache/polygene/api/composite/InvalidCompositeException.java +++ b/core/api/src/main/java/org/apache/polygene/api/composite/InvalidCompositeException.java @@ -19,14 +19,110 @@ */ package org.apache.polygene.api.composite; +import java.lang.reflect.Field; +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import org.apache.polygene.api.structure.Module; +import org.apache.polygene.api.structure.ModuleDescriptor; + /** * This exception is thrown if a Composite is invalid. */ -public class InvalidCompositeException - extends RuntimeException +public class InvalidCompositeException extends RuntimeException { - public InvalidCompositeException( String message ) + private static boolean aggregateProblems = true; + private static ThreadLocal<ArrayList<InvalidCompositeException>> report = ThreadLocal.withInitial( ArrayList::new ); + private ModuleDescriptor module; + private Class<?> primaryType; + private Class<?> fragmentClass; + private Type valueType; + private Member member; + private List<Class<?>> types; + + public static void handleInvalidCompsiteType( String message, ModuleDescriptor module, Class<?> primaryType, Class<?> fragmentClass, Type valueType, Member member, List<Class<?>> types ) + { + InvalidCompositeException exception = new InvalidCompositeException( message, module, primaryType, fragmentClass, valueType, member, types ); + if( aggregateProblems ) + { + report.get().add( exception ); + return; + } + throw exception; + } + + private InvalidCompositeException( String message, ModuleDescriptor module, Class<?> primaryType, Class<?> fragmentClass, Type valueType, Member member, List<Class<?>> types ) { super( message ); + this.module = module; + this.primaryType = primaryType; + this.fragmentClass = fragmentClass; + this.valueType = valueType; + this.member = member; + this.types = types; + } + + @Override + public String getMessage() + { + String typeNames = typesString(); + String primary = primaryType == null ? "" : " primary: " + primaryType.toGenericString() + "\n"; + String methodName = memberString(); + String message = super.getMessage() == null ? "" : " message: " + super.getMessage() + "\n"; + String fragment = fragmentClass == null ? "" : " fragmentClass: " + fragmentClass.getName() + "\n"; + String valueType = this.valueType == null ? "" : " valueType: " + this.valueType.getTypeName() + "\n"; + String module = this.module == null ? "" : " layer: " + this.module.layer().name() + "\n module: " + this.module.name() + "\n"; + return message + module + primary + fragment + methodName + valueType + typeNames; + } + + private String typesString() + { + if( types == null || types.size() == 0 ) + { + return ""; + } + return " types: " + + types.stream() + .map( Class::getSimpleName ) + .collect( Collectors.joining( ",", "[", "]" ) ) + + "\n"; + } + + private String memberString() + { + if( member == null ) + { + return ""; + } + if( member instanceof Method ) + { + Method method = (Method) member; + String parameters = Arrays.stream( method.getParameters() ).map( p -> p.getType().getSimpleName() + " " + p.getName() ).collect( Collectors.joining( ", ", "(", ")" ) ); + return " method: " + method.getReturnType().getSimpleName() + " " + method.getName() + parameters + "\n"; + } + if( member instanceof Field ) + { + Field field = (Field) member; + return " field: " + field.getType().getSimpleName() + " " + field.getName() + "\n"; + } + return member.toString(); + } + + public static String modelReport() + { + if( report.get().size() > 0 ) + { + return "\nComposition Problems Report:\n" + + report.get().stream() + .map( Throwable::getMessage ) + .map( m -> m + "\n--\n" ) + .collect( Collectors.joining( "" ) ); + } + aggregateProblems = false; + return null; } } http://git-wip-us.apache.org/repos/asf/polygene-java/blob/96de0124/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/AssemblyResportException.java ---------------------------------------------------------------------- diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/AssemblyResportException.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/AssemblyResportException.java new file mode 100644 index 0000000..0129233 --- /dev/null +++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/AssemblyResportException.java @@ -0,0 +1,60 @@ +/* + * 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.polygene.bootstrap; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * Thrown when one or more assembly problems has occurred. + */ +public class AssemblyResportException extends AssemblyException +{ + private List<Throwable> problems; + private String modelReport; + + public AssemblyResportException( List<Throwable> problems ) + { + this.problems = problems; + } + + @Override + public String getMessage() + { + String message; + if( modelReport == null ) + { + message = "\nComposition Problems Report:\n"; + } + else + { + message = modelReport; + } + return message + problems.stream() + .map( Throwable::getMessage ) + .map( m -> m + "\n--\n" ) + .collect( Collectors.joining( "" ) ); + } + + public void attacheModelReport( String modelReport ) + { + this.modelReport = modelReport; + } +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/96de0124/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ConfigurationAssembly.java ---------------------------------------------------------------------- diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ConfigurationAssembly.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ConfigurationAssembly.java deleted file mode 100644 index c827e04..0000000 --- a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ConfigurationAssembly.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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.polygene.bootstrap; - -import org.apache.polygene.api.type.HasTypes; - -/** - * This represents the assembly information of a single ConfigurationComposite in a Module. - */ -public interface ConfigurationAssembly - extends HasTypes -{ -} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/96de0124/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/Energy4Java.java ---------------------------------------------------------------------- diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/Energy4Java.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/Energy4Java.java index 88c84f1..67b6da4 100644 --- a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/Energy4Java.java +++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/Energy4Java.java @@ -21,6 +21,7 @@ package org.apache.polygene.bootstrap; import org.apache.polygene.api.PolygeneAPI; +import org.apache.polygene.api.composite.InvalidCompositeException; import org.apache.polygene.api.structure.Application; import org.apache.polygene.api.structure.ApplicationDescriptor; import org.apache.polygene.spi.PolygeneSPI; @@ -71,7 +72,22 @@ public final class Energy4Java try { ApplicationModelFactory modelFactory = runtime.applicationModelFactory(); - return modelFactory.newApplicationModel( assembly ); + ApplicationDescriptor model = modelFactory.newApplicationModel( assembly ); + String modelReport = InvalidCompositeException.modelReport(); + if( modelReport != null ) + { + throw new AssemblyException( "Composition problems\n\n" + modelReport ); + } + return model; + } + catch( AssemblyResportException e ) + { + e.attacheModelReport( InvalidCompositeException.modelReport() ); + throw e; + } + catch( AssemblyException e ) + { + throw e; } catch( RuntimeException e ) { http://git-wip-us.apache.org/repos/asf/polygene-java/blob/96de0124/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ModuleAssembly.java ---------------------------------------------------------------------- diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ModuleAssembly.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ModuleAssembly.java index 47c3729..d57b5d8 100644 --- a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ModuleAssembly.java +++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ModuleAssembly.java @@ -152,8 +152,8 @@ public interface ModuleAssembly ConfigurationDeclaration configurations( Class<?>... configurationTypes ); /** - * Given a Specification for ConfigurationAssembly's, returns a ConfigurationDeclaration that can - * be used to work with all of the assemblies matched by the specification. + * Given a Specification for Configuration, returns a ConfigurationDeclaration that can be used to work with all + * of the assemblies matched by the specification. * * @param specification The Specification that specifies the ConfigurationComposite types of interest. * http://git-wip-us.apache.org/repos/asf/polygene-java/blob/96de0124/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/CompositeAssemblyImpl.java ---------------------------------------------------------------------- diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/CompositeAssemblyImpl.java b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/CompositeAssemblyImpl.java index 709f614..bb4254d 100644 --- a/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/CompositeAssemblyImpl.java +++ b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/CompositeAssemblyImpl.java @@ -48,7 +48,6 @@ import org.apache.polygene.api.common.Optional; import org.apache.polygene.api.common.QualifiedName; import org.apache.polygene.api.common.UseDefaults; import org.apache.polygene.api.common.Visibility; -import org.apache.polygene.api.composite.InvalidCompositeException; import org.apache.polygene.api.concern.Concerns; import org.apache.polygene.api.constraint.Constraint; import org.apache.polygene.api.constraint.ConstraintDeclaration; @@ -69,6 +68,7 @@ import org.apache.polygene.api.util.Annotations; import org.apache.polygene.api.util.Classes; import org.apache.polygene.api.util.Fields; import org.apache.polygene.api.util.HierarchicalVisitorAdapter; +import org.apache.polygene.bootstrap.AssemblyResportException; import org.apache.polygene.bootstrap.StateDeclarations; import org.apache.polygene.runtime.association.AssociationModel; import org.apache.polygene.runtime.association.AssociationsModel; @@ -98,6 +98,7 @@ import org.apache.polygene.runtime.property.PropertiesModel; import org.apache.polygene.runtime.property.PropertyModel; import static java.util.stream.Stream.concat; +import static org.apache.polygene.api.composite.InvalidCompositeException.handleInvalidCompsiteType; import static org.apache.polygene.api.util.Annotations.isType; import static org.apache.polygene.api.util.Annotations.typeHasAnnotation; import static org.apache.polygene.api.util.Classes.classHierarchy; @@ -126,11 +127,11 @@ public abstract class CompositeAssemblyImpl protected MixinsModel mixinsModel; protected CompositeMethodsModel compositeMethodsModel; private AssemblyHelper helper; - protected StateDeclarations stateDeclarations; + private StateDeclarations stateDeclarations; - protected Set<String> registeredStateNames = new HashSet<>(); + private Set<String> registeredStateNames = new HashSet<>(); - public CompositeAssemblyImpl( Class<?> mainType ) + CompositeAssemblyImpl( Class<?> mainType ) { types.add( mainType ); } @@ -151,9 +152,9 @@ public abstract class CompositeAssemblyImpl return new MixinsModel(); } - protected void buildComposite( AssemblyHelper helper, - StateDeclarations stateDeclarations - ) + void buildComposite( AssemblyHelper helper, + StateDeclarations stateDeclarations + ) { this.stateDeclarations = stateDeclarations; this.helper = helper; @@ -167,7 +168,6 @@ public abstract class CompositeAssemblyImpl propertiesModel = new PropertiesModel(); stateModel = createStateModel(); mixinsModel = createMixinsModel(); -// compositeMethodsModel = new CompositeMethodsModel(); compositeMethodsModel = new CompositeMethodsModel( mixinsModel ); // Implement composite methods @@ -181,7 +181,7 @@ public abstract class CompositeAssemblyImpl concernClasses, sideEffectClasses, mixinClasses - ); + ); // Add state from methods and fields //noinspection unchecked @@ -208,86 +208,103 @@ public abstract class CompositeAssemblyImpl List<Class<?>> concernClasses, List<Class<?>> sideEffectClasses, List<Class<?>> mixinClasses - ) + ) { + List<Throwable> exceptions = new ArrayList<>(); Set<Class<?>> thisDependencies = new HashSet<>(); - types.forEach( mixinType -> { - for( Method method : mixinType.getMethods() ) - { - if( !compositeMethodsModel.isImplemented( method ) - && !Proxy.class.equals( method.getDeclaringClass().getSuperclass() ) - && !Proxy.class.equals( method.getDeclaringClass() ) - && !Modifier.isStatic( method.getModifiers() ) ) - { - MixinModel mixinModel = implementMethod( method, mixinClasses ); - ConcernsModel concernsModel = concernsFor( - method, - mixinModel.mixinClass(), - concat( concernDeclarations( mixinModel.mixinClass() ), - concernClasses.stream() ) - ); - SideEffectsModel sideEffectsModel = sideEffectsFor( - method, - mixinModel.mixinClass(), - concat( sideEffectDeclarations( mixinModel.mixinClass() ), - sideEffectClasses.stream() ) - ); - method.setAccessible( true ); - ConstraintsModel constraints = constraintsFor( - method, - toList( concat( constraintDeclarations( mixinModel.mixinClass() ), - constraintClasses.stream() ) ) - ); - CompositeMethodModel methodComposite = new CompositeMethodModel( - method, - constraints, - concernsModel, - sideEffectsModel, - mixinsModel - ); - - Stream<? extends Dependencies> source = Stream.of( methodComposite, mixinModel ); - source.flatMap( Dependencies::dependencies ) - .filter( new DependencyModel.ScopeSpecification( This.class ) ) - .map( DependencyModel::rawInjectionType ) - .forEach( thisDependencies::add ); - - interfacesOf( mixinModel.mixinClass() ) - .map( Classes.RAW_CLASS ) - .filter( clazz -> Stream.of( Initializable.class, Lifecycle.class, InvocationHandler.class ) - .noneMatch( c -> c.equals( clazz ) ) ) - .forEach( thisDependencies::add ); - - compositeMethodsModel.addMethod( methodComposite ); - } - } - // Add type to set of mixin types - mixinsModel.addMixinType( mixinType ); - } ); + types.forEach( mixinType -> + { + for( Method method : mixinType.getMethods() ) + { + try + { + if( !compositeMethodsModel.isImplemented( method ) + && !Proxy.class.equals( method.getDeclaringClass().getSuperclass() ) + && !Proxy.class.equals( method.getDeclaringClass() ) + && !Modifier.isStatic( method.getModifiers() ) ) + { + MixinModel mixinModel = implementMethod( method, mixinClasses ); + if( mixinModel != null ) + { + ConcernsModel concernsModel = concernsFor( + method, + mixinModel.mixinClass(), + concat( concernDeclarations( mixinModel.mixinClass() ), + concernClasses.stream() ) + ); + SideEffectsModel sideEffectsModel = sideEffectsFor( + method, + mixinModel.mixinClass(), + concat( sideEffectDeclarations( mixinModel.mixinClass() ), + sideEffectClasses.stream() ) + ); + method.setAccessible( true ); + ConstraintsModel constraints = constraintsFor( + method, + toList( concat( constraintDeclarations( mixinModel.mixinClass() ), + constraintClasses.stream() ) ) + ); + CompositeMethodModel methodComposite = new CompositeMethodModel( + method, + constraints, + concernsModel, + sideEffectsModel, + mixinsModel + ); + + Stream<? extends Dependencies> source = Stream.of( methodComposite, mixinModel ); + source.flatMap( Dependencies::dependencies ) + .filter( new DependencyModel.ScopeSpecification( This.class ) ) + .map( DependencyModel::rawInjectionType ) + .forEach( thisDependencies::add ); + + interfacesOf( mixinModel.mixinClass() ) + .map( Classes.RAW_CLASS ) + .filter( clazz -> Stream.of( Initializable.class, Lifecycle.class, InvocationHandler.class ) + .noneMatch( c -> c.equals( clazz ) ) ) + .forEach( thisDependencies::add ); + + compositeMethodsModel.addMethod( methodComposite ); + } + } + } + catch( Exception e ) + { + exceptions.add( e ); + } + } + // Add type to set of mixin types + mixinsModel.addMixinType( mixinType ); + } ); // Implement all @This dependencies that were found - thisDependencies.forEach( thisDependency -> { - // Add additional declarations from the @This type - Stream<Class<?>> typeConstraintClasses = concat( - constraintClasses.stream(), - constraintDeclarations( thisDependency ) ); - Stream<Class<?>> typeConcernClasses = concat( - concernClasses.stream(), - concernDeclarations( thisDependency ) ); - Stream<Class<?>> typeSideEffectClasses = concat( - sideEffectClasses.stream(), - sideEffectDeclarations( thisDependency ) ); - Stream<Class<?>> typeMixinClasses = concat( - mixinClasses.stream(), - mixinDeclarations( thisDependency ) ); - List<? extends Class<?>> singleton = Collections.singletonList( thisDependency ); - implementMixinType( singleton, - toList( typeConstraintClasses ), - toList( typeConcernClasses ), - toList( typeSideEffectClasses ), - toList( typeMixinClasses ) - ); - } ); + thisDependencies.forEach( thisDependency -> + { + // Add additional declarations from the @This type + Stream<Class<?>> typeConstraintClasses = concat( + constraintClasses.stream(), + constraintDeclarations( thisDependency ) ); + Stream<Class<?>> typeConcernClasses = concat( + concernClasses.stream(), + concernDeclarations( thisDependency ) ); + Stream<Class<?>> typeSideEffectClasses = concat( + sideEffectClasses.stream(), + sideEffectDeclarations( thisDependency ) ); + Stream<Class<?>> typeMixinClasses = concat( + mixinClasses.stream(), + mixinDeclarations( thisDependency ) ); + List<? extends Class<?>> singleton = Collections.singletonList( thisDependency ); + implementMixinType( singleton, + toList( typeConstraintClasses ), + toList( typeConcernClasses ), + toList( typeSideEffectClasses ), + toList( typeMixinClasses ) + ); + } ); + if( exceptions.size() > 0 ) + { + throw new AssemblyResportException( exceptions ); + } } @SuppressWarnings( "raw" ) @@ -311,8 +328,8 @@ public abstract class CompositeAssemblyImpl return implementMethodWithClass( method, mixinClass ); } - throw new InvalidCompositeException( "No implementation found for method \n " + method.toGenericString() - + "\nin\n " + types ); + handleInvalidCompsiteType( "No implementation found for method ", null, null, null, null, method, types ); + return null; } private Class<?> findTypedImplementation( final Method method, Stream<Class<?>> mixins ) @@ -383,8 +400,8 @@ public abstract class CompositeAssemblyImpl MixinModel model = (MixinModel) visited; Consumer<Field> addState = field -> addStateFor( field, constraintClasses ); Fields.FIELDS_OF.apply( model.mixinClass() ) - .filter( Annotations.hasAnnotation( State.class ) ) - .forEach( addState ); + .filter( Annotations.hasAnnotation( State.class ) ) + .forEach( addState ); return false; } return super.visitEnter( visited ); @@ -441,7 +458,7 @@ public abstract class CompositeAssemblyImpl protected PropertyModel newPropertyModel( AccessibleObject accessor, List<Class<?>> constraintClasses - ) + ) { List<Annotation> annotations = Annotations.findAccessorAndTypeAnnotationsIn( accessor ); boolean optional = annotations.stream().anyMatch( isType( Optional.class ) ); @@ -466,7 +483,7 @@ public abstract class CompositeAssemblyImpl } boolean useDefaults = useDefaultsDeclaration != null || stateDeclarations.useDefaults( accessor ); boolean immutable = this.immutable || metaInfo.get( Immutable.class ) != null; - InitialValueProvider initialValueProvider = metaInfo.get(InitialValueProvider.class); + InitialValueProvider initialValueProvider = metaInfo.get( InitialValueProvider.class ); return new PropertyModel( accessor, immutable, @@ -481,7 +498,7 @@ public abstract class CompositeAssemblyImpl // Model private ConstraintsModel constraintsFor( Method method, List<Class<?>> constraintClasses - ) + ) { List<ValueConstraintsModel> parameterConstraintModels = Collections.emptyList(); Annotation[][] parameterAnnotations = method.getParameterAnnotations(); @@ -496,8 +513,8 @@ public abstract class CompositeAssemblyImpl String name = nameAnnotation == null ? "param" + ( i + 1 ) : nameAnnotation.value(); boolean optional = Stream.of( parameterAnnotation ) - .filter( isType( Optional.class ) ) - .findFirst().isPresent(); + .filter( isType( Optional.class ) ) + .findFirst().isPresent(); ValueConstraintsModel parameterConstraintsModel = constraintsFor( Arrays.stream( parameterAnnotation ), parameterTypes[ i ], @@ -534,7 +551,7 @@ public abstract class CompositeAssemblyImpl boolean optional, Iterable<Class<?>> constraintClasses, AccessibleObject accessor - ) + ) { valueType = wrapperClass( valueType ); @@ -576,7 +593,7 @@ public abstract class CompositeAssemblyImpl // No implementation found! // Check if if it's a composite constraints if( Arrays.stream( annotationType.getAnnotations() ) - .anyMatch( typeHasAnnotation( ConstraintDeclaration.class ) ) ) + .anyMatch( typeHasAnnotation( ConstraintDeclaration.class ) ) ) { ValueConstraintsModel valueConstraintsModel = constraintsFor( Arrays.stream( annotationType.getAnnotations() ), @@ -592,14 +609,7 @@ public abstract class CompositeAssemblyImpl } else { - throw new InvalidCompositeException( - "Cannot find implementation of constraint @" - + annotationType.getSimpleName() - + " for " - + valueType - + " in method " - + ( (Member) accessor ).getName() - + " of composite " + types ); + handleInvalidCompsiteType( "Cannot find implementation of constraint @", null, annotationType, null, valueType, (Member) accessor, types ); } } return new ValueConstraintsModel( constraintModels, name, optional ); @@ -608,34 +618,35 @@ public abstract class CompositeAssemblyImpl private ConcernsModel concernsFor( Method method, Class<?> mixinClass, Stream<Class<?>> concernClasses - ) + ) { List<ConcernModel> concernsFor = new ArrayList<>(); - concernClasses.forEach( concern -> { - if( helper.appliesTo( concern, method, types, mixinClass ) ) - { - addConcernOrRepositionIfExists( concernsFor, helper.getConcernModel( concern ) ); - } - else - { - // Lookup method in mixin - if( !InvocationHandler.class.isAssignableFrom( mixinClass ) ) - { - try - { - Method mixinMethod = mixinClass.getMethod( method.getName(), method.getParameterTypes() ); - if( helper.appliesTo( concern, mixinMethod, types, mixinClass ) ) - { - addConcernOrRepositionIfExists( concernsFor, helper.getConcernModel( concern ) ); - } - } - catch( NoSuchMethodException e ) - { - // Ignore - } - } - } - } ); + concernClasses.forEach( concern -> + { + if( helper.appliesTo( concern, method, types, mixinClass ) ) + { + addConcernOrRepositionIfExists( concernsFor, helper.getConcernModel( concern ) ); + } + else + { + // Lookup method in mixin + if( !InvocationHandler.class.isAssignableFrom( mixinClass ) ) + { + try + { + Method mixinMethod = mixinClass.getMethod( method.getName(), method.getParameterTypes() ); + if( helper.appliesTo( concern, mixinMethod, types, mixinClass ) ) + { + addConcernOrRepositionIfExists( concernsFor, helper.getConcernModel( concern ) ); + } + } + catch( NoSuchMethodException e ) + { + // Ignore + } + } + } + } ); // Check annotations on method that have @Concerns annotations themselves for( Annotation annotation : method.getAnnotations() ) @@ -675,35 +686,36 @@ public abstract class CompositeAssemblyImpl private SideEffectsModel sideEffectsFor( Method method, Class<?> mixinClass, Stream<Class<?>> sideEffectClasses - ) + ) { List<SideEffectModel> sideEffectsFor = new ArrayList<>(); - sideEffectClasses.forEach( sideEffect -> { - SideEffectModel sideEffectModel = helper.getSideEffectModel( sideEffect ); - if( helper.appliesTo( sideEffect, method, types, mixinClass ) ) - { - addSideEffectOrRepositionIfExists( sideEffectsFor, sideEffectModel ); - } - else - { - // Lookup method in mixin - if( !InvocationHandler.class.isAssignableFrom( mixinClass ) ) - { - try - { - Method mixinMethod = mixinClass.getMethod( method.getName(), method.getParameterTypes() ); - if( helper.appliesTo( sideEffect, mixinMethod, types, mixinClass ) ) - { - addSideEffectOrRepositionIfExists( sideEffectsFor, sideEffectModel ); - } - } - catch( NoSuchMethodException e ) - { - // Ignore - } - } - } - } ); + sideEffectClasses.forEach( sideEffect -> + { + SideEffectModel sideEffectModel = helper.getSideEffectModel( sideEffect ); + if( helper.appliesTo( sideEffect, method, types, mixinClass ) ) + { + addSideEffectOrRepositionIfExists( sideEffectsFor, sideEffectModel ); + } + else + { + // Lookup method in mixin + if( !InvocationHandler.class.isAssignableFrom( mixinClass ) ) + { + try + { + Method mixinMethod = mixinClass.getMethod( method.getName(), method.getParameterTypes() ); + if( helper.appliesTo( sideEffect, mixinMethod, types, mixinClass ) ) + { + addSideEffectOrRepositionIfExists( sideEffectsFor, sideEffectModel ); + } + } + catch( NoSuchMethodException e ) + { + // Ignore + } + } + } + } ); // Check annotations on method that have @Concerns annotations themselves for( Annotation annotation : method.getAnnotations() ) @@ -735,7 +747,7 @@ public abstract class CompositeAssemblyImpl private void addSideEffectOrRepositionIfExists( List<SideEffectModel> sideEffectsFor, SideEffectModel sideEffectModel - ) + ) { // This add/remove is to allow reording of SideEffects. sideEffectsFor.remove( sideEffectModel ); @@ -800,8 +812,8 @@ public abstract class CompositeAssemblyImpl private Stream<Class<?>> mixinDeclarations( Stream<? extends Class> types ) { return types.flatMap( this::getTypes ).flatMap( Classes::typesOf ) - .filter( mixinType -> Annotations.annotationOn( mixinType, Mixins.class ) != null ) - .flatMap( mixinType -> Arrays.stream( Annotations.annotationOn( mixinType, Mixins.class ).value() ) ); + .filter( mixinType -> Annotations.annotationOn( mixinType, Mixins.class ) != null ) + .flatMap( mixinType -> Arrays.stream( Annotations.annotationOn( mixinType, Mixins.class ).value() ) ); } private Stream<Class> getAllTypes() @@ -823,7 +835,7 @@ public abstract class CompositeAssemblyImpl public AssociationModel newAssociationModel( AccessibleObject accessor, List<Class<?>> constraintClasses - ) + ) { List<Annotation> annotations = Annotations.findAccessorAndTypeAnnotationsIn( accessor ); boolean optional = annotations.stream().anyMatch( isType( Optional.class ) ); @@ -859,7 +871,7 @@ public abstract class CompositeAssemblyImpl public ManyAssociationModel newManyAssociationModel( AccessibleObject accessor, List<Class<?>> constraintClasses - ) + ) { List<Annotation> annotations = Annotations.findAccessorAndTypeAnnotationsIn( accessor ); boolean optional = annotations.stream().anyMatch( isType( Optional.class ) ); @@ -886,7 +898,7 @@ public abstract class CompositeAssemblyImpl public NamedAssociationModel newNamedAssociationModel( AccessibleObject accessor, List<Class<?>> constraintClasses - ) + ) { List<Annotation> annotations = Annotations.findAccessorAndTypeAnnotationsIn( accessor ); boolean optional = annotations.stream().anyMatch( isType( Optional.class ) ); http://git-wip-us.apache.org/repos/asf/polygene-java/blob/96de0124/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ConfigurationAssemblyImpl.java ---------------------------------------------------------------------- diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ConfigurationAssemblyImpl.java b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ConfigurationAssemblyImpl.java deleted file mode 100644 index 8bbee50..0000000 --- a/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ConfigurationAssemblyImpl.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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.polygene.runtime.bootstrap; - -import java.util.stream.Stream; -import org.apache.polygene.bootstrap.ConfigurationAssembly; - -/** - * Declaration of a EntityComposite. - */ -public final class ConfigurationAssemblyImpl - implements ConfigurationAssembly -{ - private ValueAssemblyImpl value; - private EntityAssemblyImpl entity; - - public ConfigurationAssemblyImpl( Class<?> mainType ) - { - value = new ValueAssemblyImpl( mainType ); - entity = new EntityAssemblyImpl( mainType ); - } - - @Override - public Stream<Class<?>> types() - { - return value.types(); - } -} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/96de0124/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompositeModel.java ---------------------------------------------------------------------- diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompositeModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompositeModel.java index 2f1e81d..5c2c91f 100644 --- a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompositeModel.java +++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompositeModel.java @@ -40,6 +40,7 @@ import org.apache.polygene.runtime.injection.Dependencies; import org.apache.polygene.runtime.injection.DependencyModel; import static java.lang.reflect.Proxy.newProxyInstance; +import static org.apache.polygene.api.composite.InvalidCompositeException.handleInvalidCompsiteType; /** * JAVADOC @@ -47,16 +48,18 @@ import static java.lang.reflect.Proxy.newProxyInstance; public abstract class CompositeModel implements VisitableHierarchy<Object, Object>, Dependencies, CompositeDescriptor { + protected final ModuleDescriptor module; protected final MixinsModel mixinsModel; protected final CompositeMethodsModel compositeMethodsModel; + protected final StateModel stateModel; + + private final Class<?> primaryType; private final Set<Class<?>> types; private final Visibility visibility; private final MetaInfo metaInfo; - protected final StateModel stateModel; - private volatile Class<?> primaryType; - protected Class<? extends Composite> proxyClass; - protected Constructor<? extends Composite> proxyConstructor; - protected ModuleDescriptor module; + + private Class<? extends Composite> proxyClass; + private Constructor<? extends Composite> proxyConstructor; protected CompositeModel( final ModuleDescriptor module, final List<Class<?>> types, @@ -76,7 +79,17 @@ public abstract class CompositeModel this.mixinsModel = mixinsModel; // Create proxy class - createProxyClass(); + @SuppressWarnings( "OptionalGetWithoutIsPresent" ) + Class<?> mainType = types.stream().findFirst().get(); + try + { + proxyClass = createProxyClass( mainType ); + proxyConstructor = createProxyConstructor( mainType ); + } + catch( ClassNotFoundException | NoSuchMethodException e ) + { + handleInvalidCompsiteType( e.getMessage(), module, mainType, null, null, null, types ); + } primaryType = mixinTypes() .reduce( null, ( primary, type ) -> { @@ -172,38 +185,39 @@ public abstract class CompositeModel } @SuppressWarnings( { "raw", "unchecked" } ) - private void createProxyClass() + private Class<? extends Composite> createProxyClass( Class<?> mainType ) + throws ClassNotFoundException, NoSuchMethodException { - Class<?> mainType = types.stream().findFirst().get(); + Class<? extends Composite> proxyClass; if( mainType.isInterface() ) { ClassLoader proxyClassloader = mainType.getClassLoader(); Class<?>[] interfaces = types.stream().map( Class.class::cast ).toArray( Class[]::new ); proxyClass = (Class<? extends Composite>) ProxyGenerator.createProxyClass( proxyClassloader, interfaces ); + } + else + { + proxyClass = new TransientClassLoader( getClass().getClassLoader() ).loadFragmentClass( mainType ); + } + return proxyClass; + } - try - { - proxyConstructor = proxyClass.getConstructor( InvocationHandler.class ); - } - catch( NoSuchMethodException e ) - { - throw (InvalidCompositeException) new InvalidCompositeException( "Could not get proxy constructor" ).initCause( e ); - } - proxyConstructor.setAccessible( true ); + @SuppressWarnings( { "raw", "unchecked" } ) + private Constructor<? extends Composite> createProxyConstructor( Class<?> mainType ) + throws ClassNotFoundException, NoSuchMethodException + { + Constructor<? extends Composite> constructor; + if( mainType.isInterface() ) + { + constructor = proxyClass.getConstructor( InvocationHandler.class ); } else { - try - { - proxyClass = new TransientClassLoader( getClass().getClassLoader() ).loadFragmentClass( mainType ); - proxyConstructor = (Constructor<? extends Composite>) proxyClass.getConstructors()[ 0 ]; - } - catch( ClassNotFoundException e ) - { - throw (InvalidCompositeException) new InvalidCompositeException( "Could not get proxy constructor" ).initCause( e ); - } + constructor = (Constructor<? extends Composite>) proxyClass.getConstructors()[ 0 ]; } + constructor.setAccessible( true ); + return constructor; } // Context http://git-wip-us.apache.org/repos/asf/polygene-java/blob/96de0124/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstructorsModel.java ---------------------------------------------------------------------- diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstructorsModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstructorsModel.java index bc4be4a..750a019 100644 --- a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstructorsModel.java +++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstructorsModel.java @@ -33,7 +33,6 @@ import java.util.List; import java.util.stream.Stream; import org.apache.polygene.api.common.ConstructionException; import org.apache.polygene.api.composite.CompositeDescriptor; -import org.apache.polygene.api.composite.InvalidCompositeException; import org.apache.polygene.api.injection.InjectionScope; import org.apache.polygene.api.injection.scope.Uses; import org.apache.polygene.api.util.Classes; @@ -49,6 +48,7 @@ import org.apache.polygene.runtime.injection.ParameterizedTypeInstance; import org.apache.polygene.runtime.model.Binder; import org.apache.polygene.runtime.model.Resolution; +import static org.apache.polygene.api.composite.InvalidCompositeException.handleInvalidCompsiteType; import static org.apache.polygene.api.util.Annotations.typeHasAnnotation; /** @@ -104,7 +104,7 @@ public final class ConstructorsModel { return; } - throw new InvalidCompositeException( "Inner classes can not be used. Use static nested classes instead: " + fragmentClass ); + handleInvalidCompsiteType( "Inner classes can not be used. Use static nested classes instead.", null, null, fragmentClass, null, null, null ); } @Override http://git-wip-us.apache.org/repos/asf/polygene-java/blob/96de0124/core/runtime/src/main/java/org/apache/polygene/runtime/composite/TypedModifierInvocationHandler.java ---------------------------------------------------------------------- diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/TypedModifierInvocationHandler.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/TypedModifierInvocationHandler.java index 399e3f2..d147134 100644 --- a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/TypedModifierInvocationHandler.java +++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/TypedModifierInvocationHandler.java @@ -23,6 +23,8 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import org.apache.polygene.api.composite.InvalidCompositeException; +import static org.apache.polygene.api.composite.InvalidCompositeException.handleInvalidCompsiteType; + /** * JAVADOC */ @@ -43,10 +45,6 @@ public final class TypedModifierInvocationHandler } catch( Throwable e ) { - if( fragment == null ) - { - throw new InvalidCompositeException( "No fragment available for method " + method.getName() ); - } throw cleanStackTrace( e, proxy, method ); } } http://git-wip-us.apache.org/repos/asf/polygene-java/blob/96de0124/core/runtime/src/test/java/org/apache/polygene/bootstrap/ErrorReportingTest.java ---------------------------------------------------------------------- diff --git a/core/runtime/src/test/java/org/apache/polygene/bootstrap/ErrorReportingTest.java b/core/runtime/src/test/java/org/apache/polygene/bootstrap/ErrorReportingTest.java new file mode 100644 index 0000000..7d1606d --- /dev/null +++ b/core/runtime/src/test/java/org/apache/polygene/bootstrap/ErrorReportingTest.java @@ -0,0 +1,84 @@ +/* + * 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.polygene.bootstrap; + +import java.util.Map; +import org.apache.polygene.api.association.Association; +import org.apache.polygene.api.association.ManyAssociation; +import org.apache.polygene.api.property.Property; +import org.apache.polygene.test.AbstractPolygeneTest; +import org.junit.Test; + +import static org.hamcrest.core.StringContains.containsString; +import static org.junit.Assert.assertThat; + +public class ErrorReportingTest extends AbstractPolygeneTest +{ + @Override + public void assemble( ModuleAssembly module ) + throws AssemblyException + { + module.values( Person.class ); + module.values( Pet.class ); + } + + @Override + protected void assemblyException( AssemblyException exception ) + throws AssemblyException + { + assertThat( exception.getMessage(), containsString( "Composition problems\n" ) ); + assertThat( exception.getMessage(), containsString( "Composition Problems Report:\n" ) ); + assertThat( exception.getMessage(), containsString( " message: No implementation found for method \n" + + " method: Map doAnotherThing(String name, int value)\n" + + " types: [Person,ValueComposite]\n" ) ); + + assertThat( exception.getMessage(), containsString( " message: No implementation found for method \n" + + " method: void doOneThing()\n" + + " types: [Person,ValueComposite]\n" ) ); + + assertThat( exception.getMessage(), containsString( " message: No implementation found for method \n" + + " method: void goForWalk(int minutes)\n" + + " types: [Pet,ValueComposite]\n" ) ); + } + + @Test + public void dummy() + { + + } + + public interface Person + { + void doOneThing(); + + Map<String, Integer> doAnotherThing( String name, int value ); + + Property<String> name(); + + Association<Person> spouse(); + + ManyAssociation<Pet> pets(); + } + + public interface Pet + { + void goForWalk( int minutes ); + } +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/96de0124/core/testsupport/src/main/java/org/apache/polygene/test/AbstractPolygeneBaseTest.java ---------------------------------------------------------------------- diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/AbstractPolygeneBaseTest.java b/core/testsupport/src/main/java/org/apache/polygene/test/AbstractPolygeneBaseTest.java index 18e1c24..6d7d6ba 100644 --- a/core/testsupport/src/main/java/org/apache/polygene/test/AbstractPolygeneBaseTest.java +++ b/core/testsupport/src/main/java/org/apache/polygene/test/AbstractPolygeneBaseTest.java @@ -27,7 +27,6 @@ import org.apache.polygene.api.structure.Application; import org.apache.polygene.api.structure.ApplicationDescriptor; import org.apache.polygene.bootstrap.ApplicationAssembler; import org.apache.polygene.bootstrap.ApplicationAssembly; -import org.apache.polygene.bootstrap.ApplicationAssemblyFactory; import org.apache.polygene.bootstrap.AssemblyException; import org.apache.polygene.bootstrap.Energy4Java; import org.apache.polygene.spi.PolygeneSPI; @@ -49,7 +48,7 @@ public abstract class AbstractPolygeneBaseTest throws Exception { polygene = new Energy4Java(); - applicationModel = newApplication(); + applicationModel = newApplicationModel(); if( applicationModel == null ) { // An AssemblyException has occurred that the Test wants to check for. @@ -76,20 +75,15 @@ public abstract class AbstractPolygeneBaseTest return applicationModel.newInstance( polygene.api() ); } - protected ApplicationDescriptor newApplication() + protected ApplicationDescriptor newApplicationModel() throws AssemblyException { - ApplicationAssembler assembler = new ApplicationAssembler() + ApplicationAssembler assembler = applicationFactory -> { - @Override - public ApplicationAssembly assemble( ApplicationAssemblyFactory applicationFactory ) - throws AssemblyException - { - ApplicationAssembly applicationAssembly = applicationFactory.newApplicationAssembly(); - applicationAssembly.setMode( Application.Mode.test ); - defineApplication( applicationAssembly ); - return applicationAssembly; - } + ApplicationAssembly applicationAssembly = applicationFactory.newApplicationAssembly(); + applicationAssembly.setMode( Application.Mode.test ); + defineApplication( applicationAssembly ); + return applicationAssembly; }; try http://git-wip-us.apache.org/repos/asf/polygene-java/blob/96de0124/libraries/rest/src/test/java/org/apache/polygene/library/rest/admin/RestTest.java ---------------------------------------------------------------------- diff --git a/libraries/rest/src/test/java/org/apache/polygene/library/rest/admin/RestTest.java b/libraries/rest/src/test/java/org/apache/polygene/library/rest/admin/RestTest.java index e320c99..f09e785 100644 --- a/libraries/rest/src/test/java/org/apache/polygene/library/rest/admin/RestTest.java +++ b/libraries/rest/src/test/java/org/apache/polygene/library/rest/admin/RestTest.java @@ -70,7 +70,7 @@ public class RestTest extends AbstractPolygeneTest private static final int ADMIN_PORT = FreePortFinder.findFreePortOnLoopback(); @Override - protected ApplicationDescriptor newApplication() + protected ApplicationDescriptor newApplicationModel() throws AssemblyException { return polygene.newApplicationModel( new ApplicationAssemblerAdapter(
