11 Replies Latest reply on Jul 16, 2004 12:58 PM by 101

    Scoped Ear / EJB Access

    mmccormi

      I have read through all the suggestions that I could find regarding scoped EARs but am still having an issue as I migrate to scoped ears. I would appreciate your advice.

      I have a deployment with 5 EARs. This gives you an idea of the setup.

      Security.ear
      META-INF/MANIFEST.MF
      Security-ejb.jar
      Common.jar
      META-INF/jboss-app.xml
      META-INF/application.xml

      Core.ear
      META-INF/MANIFEST.MF
      Core-ejb.jar
      Common.jar
      Security-client.jar
      META-INF/jboss-app.xml
      META-INF/application.xml

      App.ear
      META-INF/MANIFEST.MF
      Common.jar
      Core-client.jar
      Security-client.jar
      WebApp.war
      META-INF/jboss-app.xml
      META-INF/application.xml

      Each jboss-app.xml specifies a classloader and I can see invidual ones being created as I would expect via the JBoss console.

      Problem:
      I receive the following error when I try to lookup an ejb. The deployment descriptors work for a non-scoped deployment, but as I have moved to scoped ears I receive this error.

      javax.ejb.EJBException: Invalid invocation, check your deployment packaging, method=public blah, blah, blah
      at org.jboss.ejb.StatelessSessionContainer$ContainerInterceptor.invokeHome(StatelessSessionContainer.java:632)
      at org.jboss.resource.connectionmanager.CachedConnectionInterceptor.invokeHome(CachedConnectionInterceptor.java:205)
      at org.jboss.ejb.plugins.StatelessSessionInstanceInterceptor.invokeHome(StatelessSessionInstanceInterceptor.java:51)
      at org.jboss.ejb.plugins.AbstractTxInterceptor.invokeNext(AbstractTxInterceptor.java:88)
      at org.jboss.ejb.plugins.TxInterceptorCMT.runWithTransactions(TxInterceptorCMT.java:267)
      at org.jboss.ejb.plugins.TxInterceptorCMT.invokeHome(TxInterceptorCMT.java:98)
      at org.jboss.ejb.plugins.SecurityInterceptor.invokeHome(SecurityInterceptor.java:92)
      at org.jboss.ejb.plugins.LogInterceptor.invokeHome(LogInterceptor.java:120)
      at org.jboss.ejb.plugins.ProxyFactoryFinderInterceptor.invokeHome(ProxyFactoryFinderInterceptor.java:93)
      at org.jboss.ejb.StatelessSessionContainer.internalInvokeHome(StatelessSessionContainer.java:319)
      at org.jboss.ejb.Container.invoke(Container.java:720)


      The exception is thrown when the home.create() is invoked. I have checked its type and it is cast correctly. It just dies on the create.

      In my deployment the *-client.jars contain the homes, remotes, vos, exceptions. The *-ejb.jars contain everything for that systems, ie homes, remotes, EJB, vos, exceptions, defined MANIFEST.MF.

      This deployment only contains stateless session beans, no entity.

      I tried the using <!-- EAR deployer, remove if you are not using Web layers -->

      <!-- Isolate all ears in their own classloader space -->
      true
      <!-- Enforce call by value to all remote interfaces -->
      true

      for the conf/jboss-service.xml, but was unable to get the server to restart.

      Any ideas?

        • 1. Re: Scoped Ear / EJB Access
          jae77

          call by value is going to kill your performance. have you read this wiki page?

          http://www.jboss.org/wiki/Wiki.jsp?page=HotDeployClassCastExceptions

          is there any reason you need to be running scoped ears? for example, if each ear is sharing the same version of "common.jar" you'd be better off extracting that jar from all the ears and deploying it seperately.

          • 2. Re: Scoped Ear / EJB Access
            mmccormi

            The "commons" jar contains a singleton that I wanted scoped at the ear level, not server level. It also contains, general utility type classes that will not hurt if they are thrown in and redeployed out across the system.

            I am aware of the pass by value aspect of using remote stateless session beans and am willing to accept all that comes with that.

            For business reasons, we need to run scoped ears.

            Any ideas on what the problem is?

            • 3. Re: Scoped Ear / EJB Access
              jae77

              just to clarify - are you trying to invoke ejbs across ears? ie: App.ear calls ejbs in Core.ear

              • 4. Re: Scoped Ear / EJB Access
                mmccormi

                Yes.

                The App.ear would use the home and remote interface in the core-client.jar to invoke services that will execute within the Core.ear where the actual core-ejb.jar resides.

                *-client.jars contain the homes, remotes, vos, exceptions.
                *-ejb.jars contain everything for that system, homes, remotes, stateless EJB, DAOs, vos, exceptions, defined MANIFEST.MF.

                • 5. Re: Scoped Ear / EJB Access
                  jae77

                  hrm - i'm not really sure how to correct your issue. i was in somewhat of the same situation as you are, using scoped ears w/ the need to communicate and did not have much luck, even w/ setting the pass-by-value attribute to true.

                  hence the reason i did away w/ scoped ears and packaged my code as described in that wiki page. thinking out loud, i believe the issue is b/c the ears are scoped, so App.ear can not find the implementation class in Core.ear.

                  umm - do you have the ability to package the ejb implementation classes outside of the ear, but package the deployment descriptors inside the ear?

                  ie: you'd have one jar w/ all the java classes inside, and then another that contains only deployment descriptors packaged inside the ear.

                  you could also turn on classloading debugging (there is a wiki page that states how) to see if that helps produce any useful information. also, if you have access to the jboss book, chapter 2 talks about how the classloader works so it may be useful to read and digest that information and then re-approach the problem.

                  • 6. Re: Scoped Ear / EJB Access
                    mmccormi

                    I think you might be right, but that seems kinda crazy to me.

                    The unified classloader is ok, but it seems to depart from the encapsulation concept.

                    The main reason I want to do this is so I can produce a client jar for my client that will not include DAO/JDBC code, etc, etc. I want to be strict with enforcing what the clients can invoke and thus want to encapsulate all of the business code and objects behind a Facade implemented using a remote stateless session bean. This facade then resides in it's own ear out on the system, but is accessible only through the remote interface. With unified classloader, it seems everything is out on the system for anybody to access as they please.

                    It seems like the client-jar and ejb-jar is not a concept that is often used with JBoss? Any ideas? Examples? on how to use the scoped ears in the manner described above would be appreciated.

                    • 7. Re: Scoped Ear / EJB Access
                      jae77

                      i'm confused about how this is going to be deployed. are you going to "host" the server side of things and then have a client connect over some type of vpn, etc? if they were to "host" both sides, there's nothing that would prevent them from unpackaging the ears, and decompiling your classes - although i guess you could ship code using one of those tools that obscures some of that.

                      either way, using scoping is not a solution to locking down the system. for that you'd want to use jaas. an

                      i do client-jar/ejb-jar packaging all the time.

                      he's a brief example of how i do it (and this is some what modelled after how nukes is packaged, and i find it to be quite flexible).

                      1) create "api" (client) jar - inside here will go any Home/Remote interfaces, helper classes, etc. this is basically the jar you would give to the client so they could access the app.

                      2) create a "lib" jar - inside here will go any server side classes - ejb implementations, etc. no deployment descriptors are packaged here.

                      3) create "ejb" jar which contains all the deployment descriptor files, and no other classes. this allows you to do things like deploying all your entity bean classes once, but still deploy "read only" and "read/write" versions.

                      4) create an ear that contains the "lib" and "ejb" jars (and any sars you may have, wsrs, etc).

                      5) if you have any "third party" libraries, package them inside a sar (this will guarentee they get deployed first) or put them in the "lib" directory.

                      when you do your deployments to jboss, you deploy both the "api" jar that you gave to your client, plus the ear file. in addition to getting rid of those nasty ClassCastExceptions, you have the ability to hot deploy the ear if you make backend changes (not that you'd want to do this for production, but it is a great advantage in development).

                      imo, scoped ears are best if you have apps that don't need to communicate together and share different versions of a common library. if you're really concerned about who can access what, as i said before, jaas is the route you want to go.

                      • 8. Re: Scoped Ear / EJB Access
                        mmccormi

                        The desire to limit access to the DAOs, etc is more from a design perspective, not a security one. Your approach is essentially the same, except that I have always bundled my "lib" classes in with the "ejb" jar descriptors. This approach has always worked in weblogic and I assumed it would work in JBoss. The whole portable application thing. :-)

                        I will try your "lib" approach, although I am not sure why bundling the ejb implementations into a "lib" directory as opposed to the ejb.jar itself would work since they will reside in the same ear.

                        Do you know if this works with scoped ears on JBoss?

                        • 9. Re: Scoped Ear / EJB Access
                          jae77

                          are the DAOs behing the stateless session beans? or are they standalone POJOs?

                          the reason to seperate the ejb impl classes to avoid deploying the classes twice (i believe jboss will complain about this) - this makes lots of sense if you have entity beans and are planning to have a read-only and a read-write set. if you're not using entity beans, you can package them together. it's just my preference to keep all the classes together in one jar.

                          this still isn't going to work w/ the scoped ears. if you're really looking to do this type of thing, is there any reason you can't bundle the 5 deperate ears together into one big ear that is scoped? jboss allows for the russian-doll type packaging, so there's no reason that shouldn't work for you.

                          if you could give me some more details on how the app is hosted and more of what is in the individual ears and what gets given to the clients, i can try and offer some more suggestions.

                          • 10. Re: Scoped Ear / EJB Access
                            mmccormi

                            I appreciate your suggestions, but I've decided to abandon scoped ears for now. To answer your question regarding structure. The DAOs are behind POJOs which are wrapped by stateless session beans or message beans. All business logic resides in POJOs and the EJBs are just a wrapper/pass through to provide transactions, remoteness, asynchronous (MDBs), etc... The DAOs provide all data access and return simple data objects.

                            I considered the BAE (Big Ass Ear) approach, but have decided to just go with the unified class loader.

                            Thanks for your thoughts.

                            • 11. Re: Scoped Ear / EJB Access
                              101

                              same problem here: two ear's, one calls into the other. salted with the need for ear scooping.

                              jboss 3.2.5 siletly ignores the callbyvalue parameter, you need to add it to org\jboss\metadata\BeanMetaData.java

                              callByValue = callByValueElt.equalsIgnoreCase ("True");

                              in importJbossXml() at an obvious place or wait for a new release.

                              damn, i wasted an entire day... but that's just open source. but i could at least fix it... :)

                              http://sourceforge.net/tracker/index.php?func=detail&aid=992441&group_id=22866&atid=376685[/url]