4 Replies Latest reply on Apr 10, 2014 7:01 AM by Miroslav Havram

    Deploying web service from EAR's lib

    Miroslav Havram Newbie

      Hi,

       

      I would like to deploy a class (EJB3) found in a jar placed within the lib folder of an EAR as a Web Service and I would like to do it by using deployment descriptors. Deployment of the class as a SLSB by using descriptors works fine, but I do not have a success to deploy it also as a WebService. I have used this approach earlier (JBossAS 4.2.3) and it has given the desired result (EJB3 from lib folder was deployed as Web Service).

      Here is the sketch of the artifacts and the contents of the relevant ones:

       

      +-test.ear
      |
      +-lib
      | +-services.jar
      |   +-TestService.class (1)
      |
      +-depl.jar
        +-META-INF
          +-ejb-jar.xml (2)
      
      

       

      (1) - TestService.class:

       

      package test;
      
      import javax.ejb.Stateless;
      import javax.jws.WebService;
      
      @Stateless
      @WebService
      public class TestService {
           public String sayHello() {
                return "Hello, World!";
           }
      }
      
      

       

      This class is "as-is" - it's annotations have to be as they are (). Also, it cannot be deployed as an EJB (placed in the root of an EAR) because it needs to be used also as a shared library.

       

      (2) - ejb-jar.xml:

       

      <?xml version="1.0" encoding="UTF-8"?>
      <ejb-jar xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd"
        version="3.0">
        <enterprise-beans>
      
             <session>
                  <ejb-name>TestService</ejb-name>
                  <ejb-class>test.TestService</ejb-class>
                  <session-type>Stateless</session-type>
             </session>
      
        </enterprise-beans>
      </ejb-jar>
      
      

       

      Bottom line: there is a EJB3 class within a shared library that should be deployed as a Web Service somehow. Does anybody have any idea or suggestion how to achieve a desired behavior? Target is WildFly 8.0.0.Final.

      I have also tried to experiment with jboss-webservices.xml descriptors, but without a success.

       

      Thanks in advance.

        • 1. Re: Deploying web service from EAR's lib
          Stephen Coy Master

          JBossAS 4.x did not have a spec compliant class loading model, whereas JBossAS 7+ including WildFly is (mostly) spec compliant.

           

          If a jar contains EJBs then it should not be in the EAR/lib directory. It's unlikely to work correctly from there.

           

          Where are the client classes  of the "shared library" functionality located? You might have to split the shared library stuff out if it's accessed by other jars in the EAR/lib directory.

           

          In summary:

           

          • Each web module loads it's WEB-INF/classes and WEBINF/lib jars into a separate single class loader;
          • Each EJB module loads it's classes into a separate class loader;
          • All the jars in the EAR/lib directory are considered as a single module and have their own class loader;
          • Web modules can see classes from the EJB modules and the EAR/lib module. They cannot see each other's classes
          • EJB modules can see classes from the EAR/lib module. To be spec compliant they should not be able to see each other, but WildFly relaxes this.
          • Classes in the EAR/lib module cannot see EJB module classes or web module classes

           

          That's the "mostly compliant" behaviour. You can modify visibility by using manifest class path entries as described in the JavaEE specs or the jboss-deployment-structure.xml mechanism as described in Class Loading in WildFly.

          • 2. Re: Re: Deploying web service from EAR's lib
            Miroslav Havram Newbie

            Hello Stephen,

             

            Thank you for your answer and explanation. I had a feeling it has also a something with class loading.

             

            I believe that one approach to a solution would be how to make annotations from jar in EAR/lib visible to EJB in the EAR's root. As far as I understand (and experience), classes from lib/services.jar are visible to depl.jar (EJBs can be deployed by using ejb-jar.xml) but annotations are not.

             

            So far I did something and I think I have found at least some workaround to achieve desired effect. Here is what I did:

            - Generate jandex index for services.jar; result is jandex.idx

            - Put generated jandex.idx into depl.jar/META-INF

            - Package everything in the following way:

             

            +-test.ear
            |
            +-lib
            | +-services.jar
            |   +-TestService.class
            |
            +-depl.jar
             +-META-INF
               +-ejb-jar.xml
               +-jandex.idx
            

             

            after deployment I had a Web Service implemented by EJB3 from a jar found in EAR/lib.

             

            To be honest, I would rather prefer a solution with deployment descriptors instead of annotations. Why? I feel more comfortable when I have a possibility to change deployment without need to rebuild an artifact (e.g. I would like to change target namespace for Web Service for what-ever reason, but I do not want to build library again just because of that).

            I'm wondering if there is a way to achieve above-mentioned behavior but by using some kind of deployment descriptors?

            For the moment, imagine there is no EJB and/or JAX-WS annotations at all in the services.jar but EJBs are deployed by using ejb-jar.xml deployment descriptors located within depl.jar (and this works very well). Is it possible to deploy a Web Service in a similar fashion, just by using deployment descriptors and not annotations?

            • 3. Re: Re: Deploying web service from EAR's lib
              Tomaz Cerar Master

              Why you just dont put services.jar into root of jar, and in application.xml define it as ejb module.

              and then to depl.jar in MANIFEST.MF just add Class-Path entry to services.jar

               

              that should solve your ejb & classpath problems.

              • 4. Re: Re: Deploying web service from EAR's lib
                Miroslav Havram Newbie

                OK, let me give you a little bit of background information - service.jar is a product of code generator and contains EJBs, JPA entities, Web Service endpoints implemented by EJBs, etc. A very basic architecture is that EJBs operates over JPA entities and are invoked via facades implemented as Web Service endpoints. Beside services.jar, there are also other libraries making a kind of framework for an enterprise application. In general, persistence unit(s) are created from JPA entities located in several libraries (services.jar + other libraries from the framework) and also there are various EJBs in that framework which should be deployed together with EJBs located in services.jar. So far, I put everything (services.jar + framework libraries) into EAR/lib and made deployment by using deployment descriptors (persistence.xml, ejb-jar.xml, etc.) located in one common EJB used only for deployment purposes. I would like to continue in the same direction as long as it is possible (it can be expensive for us to change the whole architecture of the system at this moment). Of course, I can move services.jar to the root of an EAR but I'm a bit afraid of all other changes that would be necessary to be done and how complex they would be.

                 

                What I have noticed meanwhile is the WildFly's lack of the support for webservice.xml deployment descriptor (JSR 109, section 7.1). Is that correct or have I missed something?