polygene-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Jiri Jetmar <juergen.jet...@gmail.com>
Subject Re: Assembly proposal
Date Tue, 16 Jun 2015 08:28:59 GMT
Hi,

interessting approach - I need some more time to understand the details.

The reason for the "Tower" approach we did was that Zest Apps can be
structured
together in so many ways. When compared to e.g. the Spring/JBoss world,
where one have
a proposed and proved approach how to structure Apps, where one has
to put configurations, how/where to configure repositories and other
infrastructure.

When I joined the Zest challenge, I was somehow lost in terms of how to
structure & bootstrap
Apps in a standard, easy way.

So the proposed API can be a internal view, but from my position there is
still the external
view missing, how exactly Zest Apps should be structured.

Cheers,
Jiri

2015-05-13 9:45 GMT+02:00 Niclas Hedhman <niclas@hedhman.org>:

> Gang, (warning; long)
>
> Long tima ago, when the Assembly system was first created, we had very
> little experience of what would be needed, and kept the API very
> minimalistic. One area that was left out completely (on purpose) was to
> provide a more declarative way author the application structure.
>
> A few applications later, I keep re-implementing the same thing over and
> over. It looks like this;
>
>
>     public interface LayerAssembler
>     {
>         LayerAssembly assemble() throws AssemblyException;
>     }
>
>     public interface ModuleAssembler
>     {
>         ModuleAssembly assemble()
>             throws AssemblyException;
>     }
>
> And then implementations of those becomes like this;
>
>     public class DomainLayer
>         implements LayerAssembler
>     {
>         public static final String NAME = "domain";
>         private final LayerAssembly layer;
>
>         public DomainLayer( LayerAssembly layer )
>         {
>             this.layer = layer;
>         }
>
>         @Override
>         public LayerAssembly assemble()
>             throws AssemblyException
>         {
>             new CommandLineModule( layer.module( CommandLineModule.NAME )
> ).assemble();
>             new HostModule( layer.module( HostModule.NAME ) ).assemble();
>             new ContainersModule( layer.module( ContainersModule.NAME )
> ).assemble();
>             return layer;
>         }
>     }
>
>
>     public class CommandLineModule
>         implements ModuleAssembler
>     {
>         public static final String NAME = "domain";
>         private final ModuleAssembly module;
>
>         public CommandLineModule( ModuleAssembly module )
>         {
>             this.module = module;
>         }
>
>         @Override
>         public ModuleAssembly assemble()
>             throws AssemblyException
>         {
>             module.services( CommandLineExecutor.class ).visibleIn(
> Visibility.layer );
>             module.values( CommandLine.class );
>             return module;
>         }
>     }
>
> The reason for injecting the layer and module into the constructor instead
> of assemble() method, is because every now and then additional arguments
> might be needed.
>
> So it is all put together as
>
>     public class MyAppAssembler
>         implements ApplicationAssembler
>     {
>         private static final String NAME = "My Application Name";
>         private static final String VERSION = "1.0";
>         private final Application application;
>
>         public MyAppAssembler()
>             throws AssemblyException
>         {
>             Energy4Java qi4j = new Energy4Java();
>             ApplicationDescriptor model = qi4j.newApplicationModel( this );
>             application = model.newInstance( qi4j.spi() );
>         }
>
>         public Application application()
>         {
>             return application;
>         }
>
>         public void start()
>             throws ActivationException
>         {
>             application.activate();
>         }
>
>         public void stop()
>             throws PassivationException
>         {
>             application.passivate();
>         }
>
>         @Override
>         public ApplicationAssembly assemble( ApplicationAssemblyFactory
> applicationFactory )
>             throws AssemblyException
>         {
>             ApplicationAssembly assembly =
> applicationFactory.newApplicationAssembly();
>             assembly.setName( NAME );
>             assembly.setName( VERSION );
>             LayerAssembly infraLayer = new InfrastructureLayer(
> assembly.layer( InfrastructureLayer.NAME ) ).assemble();
>             LayerAssembly domainLayer = new DomainLayer( assembly.layer(
> DomainLayer.NAME ) ).assemble();
>             LayerAssembly serviceLayer = new ServiceLayer( assembly.layer(
> ServiceLayer.NAME ) ).assemble();
>             LayerAssembly connectivityLayer = new ConnectivityLayer(
> assembly.layer( ConnectivityLayer.NAME ) ).assemble();
>
>             connectivityLayer.uses( serviceLayer );
>             serviceLayer.uses( domainLayer );
>             serviceLayer.uses( infraLayer );
>             domainLayer.uses( infraLayer );
>             return assembly;
>         }
>     }
>
>
> So, first I would like to add the ModuleAssembler and LayerAssembler as
> Core Bootstrap classes. Secondly, I would to create a abstract class,
> perhaps named LayeredApplicationAssembler, which encapsulates the
> boilerplate code, and defines a "Layer DSL", maybe something like this;
>
>     public class MyAppAssembler extends LayeredApplicationAssembler
>     {
>         public MyAppAssembler( String name, String version, Mode mode )
>         {
>             super( name, version, mode );
>         }
>
>         protected void onAssembly()
>         {
>             LayerAssembly infraLayer = layer().definedBy( new
> InfrastructureLayer() );
>             LayerAssembly domainLayer = layer().definedBy( new
> DomainLayer() ).uses( infraLayer );
>             LayerAssembly serviceLayer = layer().definedBy( new
> ServiceLayer() ).uses( domainLayer, infraLayer );
>             layer().definedBy( new ConnectivityLayer() ).uses( serviceLayer
> );
>         }
>     }
>
> IMHO, this is quite a nice improvement over the current flexibility that
> exists.
>
> But, I have also previously mentioned that an annotated solution might be
> even cooler.
>
> public class MyAppAssembler extends AnnotatedApplicationAssembler
> {
>     @Uses( ServiceLayer.class )
>     interface ConnectivityLayer
>     {
>         ModuleAssembler MODULES = {
>             RestModule.class,
>             WebAppModule.class
>         };
>     }
>
>     @Uses( { DomainLayer.class, InfrastructureLayer.class } )
>     interface ServiceLayer
>     {
>         ModuleAssembler MODULES = {
>             DeploymentModule.class,
>             ManagementModule.class,
>             MonitoringModule.class
>         };
>     }
>
>     @Uses( InfrastructureLayer.class )
>     interface DomainLayer
>     {
>         ModuleAssembler MODULES = {
>             CommandLineModule.class,
>             HostsModule.class,
>             ContainersModule.class
>         };
>     }
>
>     interface InfrastructureLayer
>     {
>         ModuleAssembler MODULES = {
>             StorageModule.class,
>             ConfigModule.class,
>             IndexingModule.class
>         };
>     }
> }
>
> The entire application structure overview captured in a single document,
> with all the implementation detail noise removed.
> One feature that is not present without anything additional is that via the
> LayerAssembly interface, it is possible to apply cross-cutting concerns on
> Composites across an entire layer. I suggest that this is provided via
> method call in the AnnotatedApplicationAssembler super type. For instance,
> let's say that we want to apply the UnitOfWorkPropagationConcern to all
> Services in the service layer.
>
> public class MyAppAssembler extends AnnotatedApplicationAssembler
> {
>     :  // all the above at the top...
>
>     public MyAppAssembler( String name, String version, Mode mode )
>     {
>         super( name, version, mode );
>         withConcerns( UnitOfWorkPropagationConcern.class ).inLayer(
> ServiceLayer.class );
>     }
> }
>
> Looks neat enough to me, and should be able to be expanded for all the
> features that are currently possible.
>
> FINALLY,
> IF the AnnotatedApplicationAssembler also provides a complete bootstrapper,
> and we would only add
>
>     public static void main( String[] args )
>     {
>         new MyAppAssembler().run(args);
>     }
>
> then we could start things from command line, provide an abstraction for
> Application Arguments, which would also be available from a
> WebApplicationAssembler (probably a subclass of the above).
> And I am also toying with the idea that optional modules could be provided
> from the commandline, such as which entity store to be used, enabling JMX
> or Tracing, and other modules that can be made completely optional.
>
>
> WDYAT?
>
>
> Cheers
> --
> Niclas Hedhman, Software Developer
> http://zest.apache.org - New Energy for Java
>

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message