You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomee.apache.org by Karan Malhi <ka...@gmail.com> on 2011/05/28 22:30:04 UTC

Re: [CONF] OpenEJB > Configuration and Assembly

This is fantastic stuff!

On Sat, May 28, 2011 at 4:05 PM, <co...@apache.org> wrote:

>    Configuration and Assembly<https://cwiki.apache.org/confluence/display/OPENEJB/Configuration+and+Assembly> Page
> *edited* by David Blevins<https://cwiki.apache.org/confluence/display/~dblevins>
> Changes (9)
>  {note}
> Disclaimer that we do tweak and change this code frequently, without
> notice. It is the very heart of OpenEJB. To keep things tight and clean, we
> reserve the right to change it at anytime. Do not consider it a stable
> public API.
> {note}
>
> h1. Overview in Code
>
> First a glimpse of how OpenEJB looks internally. Here's a test that builds
> OpenEJB using it's internal API. This is somewhat similar to how you might
> see people constructing Jetty in code. All our internal tests look like
> this.
>
> This usage involves no xml parsing or classpath scanning. If you don't give
> it to OpenEJB, OpenEJB doesn't know about it. This is OpenEJB with all the
> magic stripped away. At a high level:
>
> Disclaimer that we do tweak and change this code frequently. It is the very
> heart of OpenEJB and we need to keep the flexibility to change it at
> anytime, so do not consider it a stable public API. If you are fine with
> some instability, you are welcome to use it. It is no doubt very powerful.
>  # You build your app in code using the JAXB tree in code and hand it to
> the {{ConfigurationFactory}}.
> ## The {{org.apache.openejb.jee}} package contains JAXB trees for
> ejb-jar.xml, beans.xml and all the Java EE deployment descriptors.
> # The {{ConfigurationFactory}} will produce a fully canonical version of
> the app called the {{Info}} tree by:
> ## Merging all sources of meta-data -- xml and annotations
> ## Resolving all ejb, persistence unit, datasource and other references
> ## Validating the app and looking for mistakes
> # The {{Info}} tree is
> ## The singular source of information about the application from this point
> forward.
> ## Pure data with no smarts or logic of any kind.
> ## The instruction set of what would be built by the assembler.
> # The {{Assembler}} will build and start the application exactly as
> described in the {{Info}} tree.
> ## When this step completes, you have a running application.
> ## Any failures prior to this point require no cleanup. Only the assembler
> builds "live" objects.
>
>
> ...
> import org.apache.openejb.jee.StatefulBean;
>
> /**
> * This test case serves as a nice tiny template for other test cases
> * and purposely doesn't do anything very complicated.
> *
> * @version $Rev$ $Date$
> */
> public class StatefulTest extends TestCase {
>
> ...
> {code}
>
> h2. Overview
> h1. Logical Overview
>
> Slightly more detailed account of the above. Our startup and deploy world
> is broken into two phases:
>
> 1. configuration (app.jar -> AppInfo) we build up a fully normalized and
> validated tree. Some of the steps are
> ...
> The listings above aren't necesarrily complete or perfectly ordered, but
> generally show the nature of the work done in each phase.
>
> h2. Configuration Phase
>
> A goal is that nothing gets through configuration and into assembly if it
> can't actually be built. The configuration phase is where we're supposed to
> wipe away any ambiguity, fully normalize the app, make sure it's internally
> consistent, spec compliant and generally good to go. If it's not, no worries
> as we actually haven't built anything permanent yet. Everything in the
> configuration phase is temporary. If it fails the configuration phase we
> just issue an error and say "App will not be loaded" and that's it, there's
> nothing to undo.
> ...
>  Full Content
> Disclaimer that we do tweak and change this code frequently, without
> notice. It is the very heart of OpenEJB. To keep things tight and clean, we
> reserve the right to change it at anytime. Do not consider it a stable
> public API.
> Overview in Code
>
> First a glimpse of how OpenEJB looks internally. Here's a test that builds
> OpenEJB using it's internal API. This is somewhat similar to how you might
> see people constructing Jetty in code. All our internal tests look like
> this.
>
> This usage involves no xml parsing or classpath scanning. If you don't give
> it to OpenEJB, OpenEJB doesn't know about it. This is OpenEJB with all the
> magic stripped away. At a high level:
>
>    1. You build your app in code using the JAXB tree in code and hand it
>    to the ConfigurationFactory.
>       1. The org.apache.openejb.jee package contains JAXB trees for
>       ejb-jar.xml, beans.xml and all the Java EE deployment descriptors.
>     2. The ConfigurationFactory will produce a fully canonical version of
>    the app called the Info tree by:
>       1. Merging all sources of meta-data – xml and annotations
>       2. Resolving all ejb, persistence unit, datasource and other
>       references
>       3. Validating the app and looking for mistakes
>     3. The Info tree is
>       1. The singular source of information about the application from
>       this point forward.
>       2. Pure data with no smarts or logic of any kind.
>       3. The instruction set of what would be built by the assembler.
>     4. The Assembler will build and start the application exactly as
>    described in the Info tree.
>       1. When this step completes, you have a running application.
>       2. Any failures prior to this point require no cleanup. Only the
>       assembler builds "live" objects.
>
> *StatefulTest.java*
>
> import javax.ejb.LocalBean;import javax.ejb.Stateful;import javax.naming.InitialContext;
> import junit.framework.TestCase;import org.apache.openejb.assembler.classic.Assembler;import org.apache.openejb.assembler.classic.SecurityServiceInfo;import org.apache.openejb.assembler.classic.TransactionServiceInfo;import org.apache.openejb.client.LocalInitialContextFactory;import org.apache.openejb.config.ConfigurationFactory;import org.apache.openejb.jee.EjbJar;import org.apache.openejb.jee.StatefulBean;
>
> public class StatefulTest extends TestCase {
>
>     @Override
>     protected void setUp() throws Exception {
>
>         System.setProperty(javax.naming.Context.INITIAL_CONTEXT_FACTORY, LocalInitialContextFactory.class.getName());
>
>         ConfigurationFactory config = new ConfigurationFactory();
>         Assembler assembler = new Assembler();
>
>         assembler.createTransactionManager(config.configureService(TransactionServiceInfo.class));
>         assembler.createSecurityService(config.configureService(SecurityServiceInfo.class));
>
>         EjbJar ejbJar = new EjbJar();
>         ejbJar.addEnterpriseBean(new StatefulBean(MyBean.class));
>
>         assembler.createApplication(config.configureApplication(ejbJar));
>     }
>
>     public void test() throws Exception {
>         InitialContext context = new InitialContext();
>         MyBean myBean = (MyBean) context.lookup("MyBeanLocalBean");
>
>         assertEquals("pan", myBean.echo("nap"));
>     }
>
>     @Stateful
>     @LocalBean
>     public static class MyBean {
>
>         public String echo(String string) {
>             StringBuilder sb = new StringBuilder(string);
>             return sb.reverse().toString();
>         }
>     }
> }
>
>  Logical Overview
>
> Slightly more detailed account of the above. Our startup and deploy world
> is broken into two phases:
>
> 1. configuration (app.jar -> AppInfo) we build up a fully normalized and
> validated tree. Some of the steps are
>
>    - read in descriptors
>    - process annotations filling in the descriptor tree
>    - validating app compliance
>    - resolving resource references
>    - resolving ejb references
>    - turning the descriptor tree into Info objects for final assembly
>    - final validation check
>
>  2. assembly (AppInfo -> actual running app) we assemble a running app as
> detailed by the AppInfo
>
>    - creating classloaders for the application
>    - creating EntityManagers and EntityManagerFactories
>    - creating live objects associated with resource-env-refs
>    - creating deployment (CoreDeploymentInfo) objects for each ejb
>    - creating the jndi enc of each ejb
>    - adding method permission objects into the security system (JACC
>    Provider)
>    - creating transaction policy objects for each ejb
>    - creating interceptor stacks and bindings for each ejb
>    - adding ejbs to containers (which may also do things like create
>    pools)
>    - adding ejbs to the live ContainerSystem registry of ejbs
>    - adding global jndi entries for each ejb
>
> The listings above aren't necesarrily complete or perfectly ordered, but
> generally show the nature of the work done in each phase.
> Configuration Phase
>
> A goal is that nothing gets through configuration and into assembly if it
> can't actually be built. The configuration phase is where we're supposed to
> wipe away any ambiguity, fully normalize the app, make sure it's internally
> consistent, spec compliant and generally good to go. If it's not, no worries
> as we actually haven't built anything permanent yet. Everything in the
> configuration phase is temporary. If it fails the configuration phase we
> just issue an error and say "App will not be loaded" and that's it, there's
> nothing to undo.
> Info Objects - Data between Configuration and Assembly
>
> The output of the configuration phase is what we call Info objects and the
> root of that tree is OpenEjbConfiguration. These objects are all simple,
> serializable data types with no methods, no constructors and no code or
> logic of any kind. We even have a test that uses ASM to walk down the Info
> tree and check that everything is compliant to these strict rules.
>
> All of the aforementioned configuration phase sits behind this info object
> tree and an interface that produces it:
>
> org.apache.openejb.assembler.classic.OpenEjbConfiguration
> org.apache.openejb.assembler.classic.OpenEjbConfigurationFactory
>
> The job of the OpenEjbConfigurationFactory is simply to produce an
> OpenEjbConfiguration tree. With this simple decoupling when the time comes
> we can actually support much different styles of use/topologies. For
> example, a cluster scenario. We could create an OpenEjbConfigurationFactory
> implementation that actually pulled the OpenEjbConfiguration from a central
> store or some sort of configuration server of our creation. Perhaps, someday
> we write an OpenEjbConfigurationFactory implementation to wrap the existing
> one and look for any changed files. If nothing has changed since last boot,
> we simple deserialize an OpenEjbConfiguration tree saved from a previous
> boot as a way of reducing startup time on very large apps.
> Assembly
>
> The assembly phase is where real running things are actually built. This
> process is inherently ingrained in the details on how OpenEJB works
> internally. Keeping it separated from descriptor parsing, validation,
> resolving, etc. keeps the actual "openejb building" code as simple as
> possible. It also allows for some flexibility and change to take place
> architecturally with less chance of it rippling through the entire system.
> However it's also not so generic (like spring, etc.) that becomes very
> difficult to get things built in a certain way or in a certain order
> requiring you to jump through several hoops just to keep the generic system
> as beautiful as possible. It knows all the details on how to build each
> individual part and in what order to build them.
>
> In OpenEJB, the Assembler is not supposed to be the gem of the project that
> we keep clean, motivating us to push complex things out into other areas for
> other people (usually users) to worry about. In fact, it's the opposite. The
> runtime system gets top priority on it's architectural needs and the
> assembler gets last priority. If there's something we can do in the
> Assembler that saves the rest of the system from complexity, we gladly throw
> the Assembler on that grenade. Our philosophy is that you can't make 100% of
> your system "perfect" all the time and sometime the mess has to go
> somewhere. The assembler is where. It's purposely not over architected so
> that it can continue to serve as a place to take up slack and not make all
> this stuff harder than it has to be.
>   Change Notification Preferences<https://cwiki.apache.org/confluence/users/viewnotifications.action>
> View Online<https://cwiki.apache.org/confluence/display/OPENEJB/Configuration+and+Assembly>| View
> Changes<https://cwiki.apache.org/confluence/pages/diffpagesbyversion.action?pageId=66260&revisedVersion=3&originalVersion=2>| Add
> Comment<https://cwiki.apache.org/confluence/display/OPENEJB/Configuration+and+Assembly?showComments=true&showCommentArea=true#addcomment>
>



-- 
Karan Singh Malhi