<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> </head> <body> <h2><span style="font-weight: bold;">Proposal</span></h2> <p>With the GF v3 module system, the module system is already responsible for instantiating many classes that constitute the application server functionality. </p> <p>The proposal is to further enhance the module system so that not only have it create objects, but also have it configure such objects by: </p> <ol> <li>injecting other objects that are needed by a newly instanciated object. </li> <li>injecting configuration information needed for that object. </li> <li>making newly created objects available, so that it can be then injected to other objects that need it. </li> </ol> <p><br> This additional service can be implemented on top of existing <tt>Lookup</tt> abstraction, by using <tt>Lookup</tt> as a place to keep the information. </p> <h3>Resource Injection</h3> <p>With this enhancement, the above code would be written as follows: </p> <pre class="code">@Requires<br>public GrizzlyAdapter adapter;<br>@Requires<br>public AdminAdapter adminAdapter;<br>public void start()
Unknown macro: {<br>adapter.registerEndpoint(adminAdapter.PREFIX_URI, adminAdapter);<br>// see later dicussion about where the command registration went<br>}
<br></pre> <p> The <tt>Resource</tt> annotation indicates the field to be injected by the module system. The type of the field and the context in which the instanciation happens is used to determine the instance to be injected. </p> <h3>Resource Extraction</h3> <p>Once services have executed, they usually provide instances of objects to other parts of the system. Such instances are usually made available through a lookup system or jndi type environments. By using the @Provides, a service indicates that the resource should be extracted once the service execution has returned successfully. </p> <pre class="code"> @Service public class ConfigService {<br> @Provides Domain domainInfo; <br> public void start()
Unknown macro: {<br> domainInfo = ....<br> }
<br>} </pre> Domain instance will be extracted and stored in the lookup service. or it can alternatively publish the service itself<br> <pre class="code"> @Service @Provides public class FooBar {<br> @Requires Domain domainInfo;<br> public void start()
Unknown macro: {...}
<br> } </pre> The FooBar service instance will be stored in the lookup for access by other services.
<h3>Scope of instances</h3> <p> In the above example both resources are "singleton" resources. That is to say, there's only one instance of it per the whole GF instance. But some objects have a different scope. For example, some objects in GF is scoped to the current thread (such as EJB <tt>InvocationContext</tt>, or security tokens), while others are scoped to the deployed application (servlet contexts, web services), yet still others are meant to be created and disposed for each use (<tt>ListApplicationCommand</tt> for example.) </p> <p>Marking classes with the scoping annotation enables the module system to inject the proper instance, for example: </p> <pre class="code"><emp>@Component(scope=THREAD)</emp><br>class InvocationContext
Unknown macro: { ... }
<br><emp>@Service(scope=SINGLETON)</emp><br>class CommandRegistry
<br><emp>@Service(scope=APPLICATION)</emp><br>class NewWebServiceContextImpl
Unknown macro: { ... }
<br><emp>@Service(scope=ONETIME)</emp><br>class ListApplicationCommand
<br></pre> <h3>Contract/implementation split</h3> <p> It is a common practice to split the contract interface and its implementation. The GF v3 module system encourages this design by separating the public class loader from the private class loader. We can take it one step further so that the actual implementations can be injected where contract is asked. Doing this requires the module system to understand what interfaces are contracts, so this calls for another annotation. </p> <pre class="code"><emp>@Contract</emp><br>interface Startup
Unknown macro: { ... }
<br><br>@Service class AdminService implements Startup
<br>@Service class ConfigService implements Startup
Unknown macro: { ... }
<br><br>class AppServerStartup
Unknown macro: {<br>@Resource<br>public List<Startup> startupServices;<br>...<br>}
<br></pre> <p> This allows the module system to recognize that <tt>AdminService</tt> and <tt>ConfigService</tt> are <tt>Startup</tt>s, and allow them to be injected into <tt>AppServerStartup.startupServices</tt>. </p> <p>An APT plugin was developed to automatically create a META-INF/service file for each @Service class implementing interfaces annotated with the @Contract. Consider the following service implementation : </p> <pre class="code"> package com.sun.v3.annotations; @Contract public interface Startup
<br> package com.wombat; @Contract public interface RandomContract
Unknown macro: {...}
<br> package com.sun.v3; @Service public class MyService implements Startup, RandomContract, PropertyChangeListener { ... } </pre> will generate the following META-INF/services files : <pre class="text"> com.sun.v3.annotations.Startup com.wombat.RandomContract </pre> with the com.sun.v3.MyService content <p>Also see the discussions that follow for the additional benefits of contract/implementation separation. </p> <h3>Named components</h3> <p> As with the case of <tt>Startup</tt>, sometimes different implementations of a contract are meant to be all used together. In other cases, components have identifiers that distinguish them among other implementations of the same contract (for example like <tt>Command</tt>, identified by the command name.) </p> <p>While in theory such "identifier" is quite open-ended, in practice, a string identifier seems to be working just fine with most existing IoC containers. So we allow components to have names, like this: </p> <pre class="code">@Contract interface Command
Unknown macro: { ... }
<br><emp>@Service(name="stop-domain")</emp><br>class StopDomainCommand
<br><emp>@Service(name="list-applications")</emp><br>class ListApplicationsCommand
Unknown macro: { ... }
<br></pre> <p> The exact meaning of the name depends on the contract for which the class is exposed. In the above example the intention is that the name is used as the command name. </p> <p>Named components are often used for manually looking up resources, as opposed to automatic injection via <tt>@Resource</tt>, since often the name is only available after some computation. The example is shown below: </p> <pre class="code">class AdminAdapter {<br>@Requires<br>Lookup lookup;<br>...<br>public void service(Request req, Response res)
Unknown macro: {<br>...<br>String commandName = ...;<br>Command cmd = lookup.lookup(Command.class,commandName);<br>cmd.execute(...);<br>}
<br>}<br></pre> <h3>Service Ordering</h3> The combination of @Requires and @Provides annotations provide an ability to calculate the order of services initialization by looking at the list of resources required and provided by each service and arrange the services initialization automtically. This is calculated at runtime since the services implementation are implemented in different modules and can be added dynamically to the V3 repositories. <h3>Lazy injection</h3> <p> Another possible useful service on top of this abstraction is to inject a smart <tt>List</tt> that defers the actual injection. For example, we can inject all <tt>Startup</tt>s lazily when it's accessed for the first time. This makes the code simpler by avoiding the separation between initialization and storage: </p> <pre class="code">class MyCode {<br><emp>@Lazy</emp> @Resource<br>public List<Startup> startups;<br>...<br>void f()
Unknown macro: {<br>for( Startup s }
<br>}<br></pre> <p> Or a smart <tt>Map</tt> could be used and have named : </p> <pre class="code">class MyCode {<br><emp>@Lazy</emp> @Resource<br>public Map<String,Command> commands;<br>...<br>void f()
Unknown macro: {<br>Command c = commands.get("list-domains"); // this will instanciate a properly configured ListDomainsCommand<br>}
<br>}<br></pre> <h3>Half-baked: Configuration injection</h3> <p> The other thing we should inject is the configuration information. I'm not too familiar about the kind of configurations GF has, but for example, perhaps something like this for system property: </p> <pre class="code">class PhobosContainer
Unknown macro: {<br>@Resource(<emp>"phobos.home"</emp>)<br>public File home;<br>}
<br></pre> ... and perhaps something like this for the configuration in domain.xml <pre class="code">class GrizzlyService
Unknown macro: {<br>// some kind of path expression over JavaBeans<br>@Resource(<emp>"domain.config.httpService.httpListner.port"</emp>)<br>public int port;<br>}
<br></pre> <p> It's not clear if we should reuse <tt>@Resource</tt> or create a new annotation, or it's not clear if we need a single symbol space for all configurations or different annotations for each distinct configuration space. This needs more discussion. <!-- ==================================================================================================== --></p> </body> </html>
|