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.

Reply via email to