tomee-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From David Blevins <david.blev...@gmail.com>
Subject Re: override annotation based configuration with ejb-jar.xml
Date Thu, 30 Jun 2011 02:43:17 GMT
On Jun 27, 2011, at 1:44 PM, kubamarchwicki wrote:

> Here is my issue with OpenEJB. I'm note sure if what I'm trying to do is not
> possible or I'm doing something wrong. 

Saw your article and I don't think you're doing anything "wrong".  Maybe the existing set
of features don't fully cover what you're trying to do -- or maybe they do, but not in a convenient
way.  Either way, most of the existing features came from user requests, so hopefully we can
mine some gems from your experience.

> I use OpenEJB only for testing - embedded container. In the application I
> have multiple beans implementing same business interface, one main - with
> logic, few other in tests. What I'm looking for is possibility to (after
> bootstrapping container) override wired dependencies with the testing
> implementation.

I'd like to spend some time attempting to do the things you describe -- walk in your shoes,
so to speak.  Might be a day or two before I can do that.  In the meantime, can you take a
look at this technique.  It's how we write our internal tests and is a big influence on Arquillian
-- OpenEJB was a pretty critical part of Arquillian when they were first getting it going.

  http://people.apache.org/~dblevins/application-composer/
  http://people.apache.org/~dblevins/application-composer.zip

This is the main guy to look at:

  http://people.apache.org/~dblevins/application-composer/src/test/java/org/superbiz/composed/MoviesTest.java

Basically with this approach there is zero classpath scanning.  The only thing built is what
you give OpenEJB directly, regardless of what is floating around in your classpath.  It's
also not really integration testing as the idea is that you isolate the component (or two)
you want to test and just test that small controlled number of components.

Mixing the worlds of fully integration testing and doing this more true unit testing is certainly
something I've thought of.  Making small adjustments to a large app is not yet as easy as
it should be -- the alternative xml approach is only so useful.  

One thought that I've had is to maybe come up with some hybrid.  Some sort of visitor pattern
where, like you mention, the test case can make programmatic changes to the application before
it is deployed.

Before we actually start building anything, our "deployment" process looks like this:

    1 scan for apps in the classpath
    2 read in descriptors
    3 scan for @Stateful, @Singleton, @Stateless, @MessageDriven
    4 process annotations for known components (the above, plus those in xml)
    5 validating app compliance
    6 resolving resource references
    7 resolving ejb references
    8 turning the descriptor tree into Info objects for final assembly
    9 final validation check

Between before and after step 4 would be prime places for some developer hooks.  Before 4
you could swap out the implementations of components.  After 4 you could change any part of
the metadata for an app regardless if it came from annotations or xml -- after 4 we have pulled
all the annotation data out and essentially put the data in the objects we use to represent
the descriptor.

One thought as to how to offer such hooks might be to do something like the ApplicationComposer
but instead of @Module methods that produce (return) various things like EjbJar or SessionBean
or PersistenceUnit, we instead have methods that take them as arguments (basically visitor
methods).  Something like:

  @PreProcess 
  public void anymethodName(EjbJar ejbJar) {
     // do anything you want to the app before we do step 4
  }

  @PostProcess 
  public void anymethodName(EjbJar ejbJar) {
     // do anything you want to the app after we do step 4
  }


-David

> How I understand OpenEJB lifecycle, first ejb-jar.xml is evaluated. After
> that - class path discovery is performed. In either cases it doesn't work
> for me. When I put something like this in ejb-jar.xml a NullPointer is
> thrown (MethodController is my business service,
> AnotherTestingDisplayingService is a testing mockup)
>        <session>
>            <ejb-name>MethodController</ejb-name>
>            <ejb-ref>
> 
> <ejb-ref-name>pl.marchwicki.ejb.controllers.MethodController/displayingService</ejb-ref-name>
> 
> <remote>pl.marchwicki.ejb.view.DisplayingServiceLocal</remote>
>                <ejb-link>AnotherTestingDisplayingService</ejb-link>
>                <injection-target>
> 
> <injection-target-class>pl.marchwicki.ejb.controllers.MethodController</injection-target-class>
> 
> <injection-target-name>displayingService</injection-target-name>
>                </injection-target>
>            </ejb-ref>
> 
> Sounds reasonable, MethodController is not yet present in context. 
> 
> On the other hand, when I fully define MethodController in ejb-jar.xml (like
> this)
> <session id="MethodController">
>            <ejb-name>MethodController</ejb-name>
>            <mapped-name></mapped-name>
> 
> <business-local>pl.marchwicki.ejb.controllers.MethodControllerLocal</business-local>
> 
> <ejb-class>pl.marchwicki.ejb.controllers.MethodController</ejb-class>
>            <session-type>Stateless</session-type>
>            <transaction-type>Container</transaction-type>
>            <ejb-ref>
> 
> <ejb-ref-name>pl.marchwicki.ejb.controllers.MethodController/displayingService</ejb-ref-name>
> 
> <remote>pl.marchwicki.ejb.view.DisplayingServiceLocal</remote>
>                <ejb-link>AnotherTestingDisplayingService</ejb-link>
>                <injection-target>
> 
> <injection-target-class>pl.marchwicki.ejb.controllers.MethodController</injection-target-class>
> 
> <injection-target-name>displayingService</injection-target-name>
>                </injection-target>
>            </ejb-ref>
>            <ejb-ref>
> 
> <ejb-ref-name>pl.marchwicki.ejb.controllers.MethodController/calculatingService</ejb-ref-name>
> 
> <remote>pl.marchwicki.ejb.business.CalculatingServiceLocal</remote>
>                <injection-target>
> 
> <injection-target-class>pl.marchwicki.ejb.controllers.MethodController</injection-target-class>
> 
> <injection-target-name>calculatingService</injection-target-name>
>                </injection-target>
>            </ejb-ref>
>        </session>  
> 
> I get javax.naming.NameAlreadyBoundException when classpath discovery is
> performed. 
> Either way my mocking doesn't work. 
> 
> Similar problem happens when multiple ears are collapsed into single
> classpath.ear (on tests). When multiple implementations of same business
> interface are present across different ears, there is not way in OpenEJB to
> manually pick up desired implementation. 
> 
> My question is - am I doing something wrong or I'm trying to 'beat the game'
> and doing things which OpenEJB wasn't designed for.
> 
> The code for this example is on my github
> (https://github.com/kubamarchwicki/ejb-testing) if some reference is needed.
> 
> many thanks
> Jakub
> 
> --
> View this message in context: http://openejb.979440.n4.nabble.com/override-annotation-based-configuration-with-ejb-jar-xml-tp3628804p3628804.html
> Sent from the OpenEJB User mailing list archive at Nabble.com.


Mime
View raw message