13 Replies Latest reply on Jan 16, 2014 3:22 PM by ajay.deshwal

    Classes in a WAR packaged inside an EAR are not visible to SwitchYard runtime

    ajay.deshwal

      Hello Everyone,

       

      I am using switchyard for developing an application which consists of multiple modules / SwitchYard composites. My project structure consists of an EAR that wraps multiple jars and a couple of war modules. All modules are SwitchYard applications. The web module switchyard.xml looks like following:

       

      <?xml version="1.0" encoding="UTF-8"?>

      <switchyard xmlns="urn:switchyard-config:switchyard:1.0" xmlns:sy="urn:switchyard-config:switchyard:1.0" xmlns:bean="urn:switchyard-component-bean:config:1.0" xmlns:resteasy="urn:switchyard-component-resteasy:config:1.0" xmlns:sca="http://docs.oasis-open.org/ns/opencsa/sca/200912" name="myproject-api" targetNamespace="urn:com.example:myproject-api:1.0">

        <sca:composite name="myproject-api" targetNamespace="urn:com.example:myproject-api:1.0">

          <sca:component name="UserServiceComponet">

            <bean:implementation.bean class="com.example.api.user.UserServiceImpl"/>

            <sca:service name="UserService">

              <sca:interface.java interface="com.example.api.user.UserService"/>

            </sca:service>

            <sca:reference name="UserFacade">

              <sca:interface.java interface="com.example.api.user.UserFacade"/>

            </sca:reference>

          </sca:component>

          <sca:component name="UserResource">

            <bean:implementation.bean class="com.example.api.rest.user.UserResource"/>

            <sca:reference name="UserService">

              <sca:interface.java interface="com.example.api.user.UserService"/>

            </sca:reference>

          </sca:component>

          <sca:reference name="UserFacade" multiplicity="0..1" promote="UserServiceComponet/UserFacade">

            <sca:interface.java interface="com.example.api.user.UserFacade"/>

            <sca:binding.sca sy:target="UserFacade" sy:targetNamespace="urn:com.example:myproject-core:1.0" name="UserFacade"/>

          </sca:reference>

        </sca:composite>

      </switchyard>

       

       

      Following is the error trace:

       

      00:24:25,563 ERROR [org.jboss.msc.service.fail] (MSC service thread 1-3) MSC000001: Failed to start service jboss.deployment.unit."myproject-ear.ear".WeldStartService: org.jboss.msc.service.StartException in service jboss.deployment.unit."myproject-ear.ear".WeldStartService: Failed to start service

        at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1767) [jboss-msc-1.0.4.GA-redhat-1.jar:1.0.4.GA-redhat-1]

        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [rt.jar:1.7.0_45]

        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [rt.jar:1.7.0_45]

        at java.lang.Thread.run(Thread.java:744) [rt.jar:1.7.0_45]

      Caused by: org.jboss.weld.exceptions.DefinitionException: Exception List with 1 exceptions:

      Exception 0 :

      java.lang.IllegalArgumentException: interface com.example.api.user.UserService is not visible from class loader

        at java.lang.reflect.Proxy.getProxyClass0(Proxy.java:487)

        at java.lang.reflect.Proxy.newProxyInstance(Proxy.java:722)

        at org.switchyard.component.bean.ClientProxyBean.<init>(ClientProxyBean.java:103)

        at org.switchyard.component.bean.SwitchYardCDIServiceDiscovery.addClientProxyBean(SwitchYardCDIServiceDiscovery.java:174)

        at org.switchyard.component.bean.SwitchYardCDIServiceDiscovery.addInjectableClientProxyBean(SwitchYardCDIServiceDiscovery.java:162)

        at org.switchyard.component.bean.SwitchYardCDIServiceDiscovery.processBean(SwitchYardCDIServiceDiscovery.java:107)

        at sun.reflect.GeneratedMethodAccessor5.invoke(Unknown Source)

        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

        at java.lang.reflect.Method.invoke(Method.java:606)

        at org.jboss.weld.util.reflection.SecureReflections$13.work(SecureReflections.java:267)

        at org.jboss.weld.util.reflection.SecureReflectionAccess.run(SecureReflectionAccess.java:52)

        at org.jboss.weld.util.reflection.SecureReflectionAccess.runAsInvocation(SecureReflectionAccess.java:137)

        at org.jboss.weld.util.reflection.SecureReflections.invoke(SecureReflections.java:263)

        at org.jboss.weld.introspector.jlr.WeldMethodImpl.invokeOnInstance(WeldMethodImpl.java:170)

        at org.jboss.weld.introspector.ForwardingWeldMethod.invokeOnInstance(ForwardingWeldMethod.java:51)

        at org.jboss.weld.injection.MethodInjectionPoint.invokeOnInstanceWithSpecialValue(MethodInjectionPoint.java:154)

        at org.jboss.weld.event.ObserverMethodImpl.sendEvent(ObserverMethodImpl.java:245)

        at org.jboss.weld.event.ObserverMethodImpl.sendEvent(ObserverMethodImpl.java:233)

        at org.jboss.weld.event.ObserverMethodImpl.notify(ObserverMethodImpl.java:213)

        at org.jboss.weld.event.ObserverNotifier.notifyObserver(ObserverNotifier.java:117)

        at org.jboss.weld.event.TransactionalObserverNotifier.notifyObserver(TransactionalObserverNotifier.java:44)

        at org.jboss.weld.event.ObserverNotifier.notifyObservers(ObserverNotifier.java:85)

        at org.jboss.weld.event.ObserverNotifier.fireEvent(ObserverNotifier.java:75)

        at org.jboss.weld.bootstrap.events.AbstractContainerEvent.fire(AbstractContainerEvent.java:60)

        at org.jboss.weld.bootstrap.events.AbstractDefinitionContainerEvent.fire(AbstractDefinitionContainerEvent.java:38)

        at org.jboss.weld.bootstrap.events.ProcessManagedBeanImpl.fire(ProcessManagedBeanImpl.java:30)

        at org.jboss.weld.bootstrap.AbstractBeanDeployer.deploy(AbstractBeanDeployer.java:124)

        at org.jboss.weld.bootstrap.BeanDeployment.deployBeans(BeanDeployment.java:217)

        at org.jboss.weld.bootstrap.WeldBootstrap.deployBeans(WeldBootstrap.java:357)

        at org.jboss.as.weld.WeldStartService.start(WeldStartService.java:63)

        at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1811)

        at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1746)

        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)

        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)

        at java.lang.Thread.run(Thread.java:744)

       

       

        at org.jboss.weld.bootstrap.events.AbstractDefinitionContainerEvent.fire(AbstractDefinitionContainerEvent.java:40)

        at org.jboss.weld.bootstrap.events.ProcessManagedBeanImpl.fire(ProcessManagedBeanImpl.java:30)

        at org.jboss.weld.bootstrap.AbstractBeanDeployer.deploy(AbstractBeanDeployer.java:124)

        at org.jboss.weld.bootstrap.BeanDeployment.deployBeans(BeanDeployment.java:217)

        at org.jboss.weld.bootstrap.WeldBootstrap.deployBeans(WeldBootstrap.java:357)

        at org.jboss.as.weld.WeldStartService.start(WeldStartService.java:63)

        at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1811) [jboss-msc-1.0.4.GA-redhat-1.jar:1.0.4.GA-redhat-1]

        at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1746) [jboss-msc-1.0.4.GA-redhat-1.jar:1.0.4.GA-redhat-1]

        ... 3 more

       

       

      00:24:25,890 INFO  [org.jboss.as.server] (ServerService Thread Pool -- 27) JBAS018559: Deployed "myproject-ear.ear" (runtime-name : "myproject--ear.ear")

      00:24:25,896 INFO  [org.jboss.as.controller] (Controller Boot Thread) JBAS014774: Service status report

      JBAS014775:    New missing/unsatisfied dependencies:

            service jboss.deployment.subunit."myproject-ear.ear"."myproject-webapp-0.0.1-SNAPSHOT.war".deploymentCompleteService (missing) dependents: [service jboss.deployment.unit."myproject-ear.ear".deploymentCompleteService]

      JBAS014777:   Services which failed to start:      service jboss.deployment.unit."myproject--ear.ear".WeldStartService: org.jboss.msc.service.StartException in service jboss.deployment.unit."myproject-ear.ear".WeldStartService: Failed to start service

       

       

       

       

       

      It seems like the switchyard runtime uses ear classloader to create a proxy of the Component Bean interface but the classloader cannot see the classes inside ear file.

      I am using switchyard version 1.1.0 on EAP 6.1.1.

       

      Please help me move forward. Any pointers will be much appreciated,

       

      Thanks

      Ajay

        • 1. Re: Classes in a WAR packaged inside an EAR are not visible to SwitchYard runtime
          ajay.deshwal

          Just to add, everything works fine if I deploy the same war package out of the ear.

          • 2. Re: Classes in a WAR packaged inside an EAR are not visible to SwitchYard runtime
            igarashitm

            I'm not really clear what's the problem on it, but have you tried jboss-deployment-structure.xml to control the subdeployment dependency?

            Class Loading in AS7 - JBoss AS 7.0 - Project Documentation Editor

             

            hth,

            Tomo

            • 3. Re: Classes in a WAR packaged inside an EAR are not visible to SwitchYard runtime
              ajay.deshwal

              Hi Tomo,

               

              Thanks for the response. In my understanding, I do not have to set up any sub-deployment dependency. The switchyard subsystem automatically scans the ear sub-deployments and initialize the switchyard components required for each switchyard application packaged inside ear. The problem in my case is that switchyard starts deploying the war module inside ear but the classloader is unable to find component interfaces while creating proxy instances. In my view, one needs to add a sub-deployment dependency if the war module is not able to access any dependent module but not the other way around. Please correct me if I am wrong.

              I think the problem is that the switchyard runtime tries to deploy switchyard components inside the war module using the ear classloader but unlike other types of ear sub-modules the war module classloader is always isolated (as per specifications). That is why the jar sub modules are deploying fine but not the war.

              I have gone through switchyard quickstarts but none of the example demonstrates  a war packaged inside an ear. The following ear quickstart has only jar type sub-modules. quickstarts/ear-deployment at master · jboss-switchyard/quickstarts · GitHub

               

              The easiest way to replicate the problem would be to package any switchyard war type quickstart inside an ear and deploy it.

               

              Thanks

              Ajay

              • 4. Re: Classes in a WAR packaged inside an EAR are not visible to SwitchYard runtime
                kcbabo

                Is there a reason why you can't package the shared classes inside a jar inside the EAR/lib directory?  This provides a bit more flexibility under default Java EE class loading rules and avoids having to play with deployment-structure.  In general, we recommend you always put shared classes/resources in a separate jar/module, whether it's packaged in an EAR or deployed separately.

                • 5. Re: Classes in a WAR packaged inside an EAR are not visible to SwitchYard runtime
                  ajay.deshwal

                  Thanks for the response Keith. That is how I worked around the class-loader problem, i.e., by packaging all SwitchYard interfaces used by Component, Composite Service and References into a separate jar and adding it to EAR/lib directory. But in my view, these interfaces do not come in the category of shared classes of the application. We can call Composite Service and Reference interfaces as shared resources if I am using SCA binding to expose and consume services across SwitchYard applications and intend to utilize same interface classes for exposing a service from one app and consuming from another. By shared if you meant, shared between application and Switchyard runtime then also I am not sure if it is a good practice to package interfaces in a jar just to make them visible to SwitchYard deployer classloader. Please correct if I am missing anything.

                   

                  Sorry for not posting the solution here, I was just waiting for some time to get a better solution from the community before posting something that I personally do not see as a good practice.

                  Just a suggestion though, can the SwitchYard deployer modified to use a sub-deployment classloader in case the sub-deployment is a WAR instead of using parent deployment (EAR) classloader?

                   

                  Thanks! And Happy New Year folks!

                  • 6. Re: Classes in a WAR packaged inside an EAR are not visible to SwitchYard runtime
                    kcbabo

                    By "shared" I mean that two or more SY applications use the same class or resource.  Even if all your applications are packaged inside an EAR, it's a best practice to isolate these shared resources/classes into a distinct module.  This keeps the dependency graph clean and ensures that only one version of a class/resource is loaded/used.

                    • 7. Re: Classes in a WAR packaged inside an EAR are not visible to SwitchYard runtime
                      ajay.deshwal

                      I understand and agree that the shared interface classes should be packaged inside a common/shared dependency jar. But all the interface classes of the applications that are associated with SY are not always shared across SY applications. Like i mentioned, typically the interfaces may be shared if SY applications are exposing and consuming services through SCA bindings or may be in some other scenarios as well but that is not always the case. Moreover, Component interfaces are usually private to the SY application.


                      For instance, lets say we have an EAR that has SY applications packaged as JAR and WAR inside it. A WAR module has multiple composite references for consuming services through multiple types of bindings and only few of them are SCA targeting to services exposed by one of the other SY applications in EAR. The WAR module also exposes multiple composite services through different types of bindings. In this scenario, only the interface classes associated with the SCA reference can be deemed as shared in my view. Rest all are private to the SY application. If I keep these interfaces packaged inside WAR, the application won't deploy. For the application to deploy successfully, all the interfaces needs to be extracted into a separate JAR and added as an EAR dependency.

                       

                      Am I correct in assuming that the only solution at the moment is to package all SY associated interfaces of the SY application inside a shared jar and add it as EAR dependency especially when the SY application is packaged as a WAR?

                      If yes, can it be categorized as a bug or expected/correct behaviour of SY application deployer?

                       

                      Thanks.

                      • 8. Re: Re: Classes in a WAR packaged inside an EAR are not visible to SwitchYard runtime
                        kcbabo

                        The only interfaces that need to be packaged in a common module are shared interfaces.  If you see an issue where private interfaces/classes need to be moved outside the WAR, can you please attach a basic application which can be used to reproduce the behavior?

                         

                        One thing to keep in mind here is that an EAR with multiple SY modules is actually multiple applications from a SY deployment perspective.  For example:

                         

                        myapp.ear
                        +- myweb.war (switchyard.xml)
                        +- sy1.jar (switchyard.xml)
                        +- sy2.jar (switchyard.xml)
                        +- lib
                          +- shared.jar
                        

                         

                        In the above scenario, there are three SY applications from a deployment perspective, not one.  This means that any interfaces/classes shared between myweb.war and sy1.jar (via binding.sca for example) will need to be packaged in a separate module (e.g. shared.jar).

                        • 9. Re: Re: Re: Classes in a WAR packaged inside an EAR are not visible to SwitchYard runtime
                          ajay.deshwal

                          Thanks for the response Keith. Yes, I understand what you have explained about the SY applications inside an EAR.

                          I have attached a sample EAR application that replicates the problems and explains the scenario I have been talking about. Please take a look.

                           

                          Thanks!

                          • 10. Re: Classes in a WAR packaged inside an EAR are not visible to SwitchYard runtime
                            kcbabo

                            I have not had a chance to deploy/test the app, but I had a quick look just now.  I'm wondering if the local name of the bean interface is being used somewhere instead of the fully qualified (package + class) name.  There's a UserService local to the web project and another UserService in the common project, which may expose an underlying issue in SwitchYard/CDI.  Can you update the name of the UserService interface used in the component reference in the web project to be something like UserServiceWeb?  You will need to update the switchyard.xml and the bean using the interface injection as well.  Refactor support in Eclipse should take care of this *if* you enable the "Update fully qualified names in non-Java text files" option which is disabled by default.

                            • 11. Re: Classes in a WAR packaged inside an EAR are not visible to SwitchYard runtime
                              ajay.deshwal

                              Hi Keith,

                               

                              Thanks for your inputs, However, I checked and found no interface with name UserService in common module. There is one with name UserManager. I still tried changing the name of the one in web module to UserServiceWeb, but facing the same error :

                               

                              23:27:38,580 ERROR [org.jboss.msc.service.fail] (MSC service thread 1-2) MSC000001: Failed to start service jboss.deployment.unit."sample-ear.ear".WeldStartService: org.jboss.msc.service.StartException in service jboss.deployment.unit."sample-ear.ear".WeldStartService: Failed to start service

                                  at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1767) [jboss-msc-1.0.4.GA-redhat-1.jar:1.0.4.GA-redhat-1]

                                  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [rt.jar:1.7.0_45]

                                  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [rt.jar:1.7.0_45]

                                  at java.lang.Thread.run(Thread.java:744) [rt.jar:1.7.0_45]

                              Caused by: org.jboss.weld.exceptions.DefinitionException: Exception List with 1 exceptions:

                              Exception 0 :

                              java.lang.IllegalArgumentException: interface com.example.sample.web.UserServiceWeb is not visible from class loader

                                  at java.lang.reflect.Proxy.getProxyClass0(Proxy.java:487)

                                  at java.lang.reflect.Proxy.newProxyInstance(Proxy.java:722)

                                  at org.switchyard.component.bean.ClientProxyBean.<init>(ClientProxyBean.java:103)

                                  at org.switchyard.component.bean.SwitchYardCDIServiceDiscovery.addClientProxyBean(SwitchYardCDIServiceDiscovery.java:174)

                                  at org.switchyard.component.bean.SwitchYardCDIServiceDiscovery.addInjectableClientProxyBean(SwitchYardCDIServiceDiscovery.java:162)

                                  at org.switchyard.component.bean.SwitchYardCDIServiceDiscovery.processBean(SwitchYardCDIServiceDiscovery.java:107)

                                  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

                                  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)

                                  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

                                  at java.lang.reflect.Method.invoke(Method.java:606)

                                  at org.jboss.weld.util.reflection.SecureReflections$13.work(SecureReflections.java:267)

                                  at org.jboss.weld.util.reflection.SecureReflectionAccess.run(SecureReflectionAccess.java:52)

                                  at org.jboss.weld.util.reflection.SecureReflectionAccess.runAsInvocation(SecureReflectionAccess.java:137)

                                  at org.jboss.weld.util.reflection.SecureReflections.invoke(SecureReflections.java:263)

                                  at org.jboss.weld.introspector.jlr.WeldMethodImpl.invokeOnInstance(WeldMethodImpl.java:170)

                                  at org.jboss.weld.introspector.ForwardingWeldMethod.invokeOnInstance(ForwardingWeldMethod.java:51)

                                  at org.jboss.weld.injection.MethodInjectionPoint.invokeOnInstanceWithSpecialValue(MethodInjectionPoint.java:154)

                                  at org.jboss.weld.event.ObserverMethodImpl.sendEvent(ObserverMethodImpl.java:245)

                                  at org.jboss.weld.event.ObserverMethodImpl.sendEvent(ObserverMethodImpl.java:233)

                                  at org.jboss.weld.event.ObserverMethodImpl.notify(ObserverMethodImpl.java:213)

                                  at org.jboss.weld.event.ObserverNotifier.notifyObserver(ObserverNotifier.java:117)

                                  at org.jboss.weld.event.TransactionalObserverNotifier.notifyObserver(TransactionalObserverNotifier.java:44)

                                  at org.jboss.weld.event.ObserverNotifier.notifyObservers(ObserverNotifier.java:85)

                                  at org.jboss.weld.event.ObserverNotifier.fireEvent(ObserverNotifier.java:75)

                                  at org.jboss.weld.bootstrap.events.AbstractContainerEvent.fire(AbstractContainerEvent.java:60)

                                  at org.jboss.weld.bootstrap.events.AbstractDefinitionContainerEvent.fire(AbstractDefinitionContainerEvent.java:38)

                                  at org.jboss.weld.bootstrap.events.ProcessManagedBeanImpl.fire(ProcessManagedBeanImpl.java:30)

                                  at org.jboss.weld.bootstrap.AbstractBeanDeployer.deploy(AbstractBeanDeployer.java:124)

                                  at org.jboss.weld.bootstrap.BeanDeployment.deployBeans(BeanDeployment.java:217)

                                  at org.jboss.weld.bootstrap.WeldBootstrap.deployBeans(WeldBootstrap.java:357)

                                  at org.jboss.as.weld.WeldStartService.start(WeldStartService.java:63)

                                  at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1811)

                                  at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1746)

                                  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)

                                  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)

                                  at java.lang.Thread.run(Thread.java:744)

                               

                                  at org.jboss.weld.bootstrap.events.AbstractDefinitionContainerEvent.fire(AbstractDefinitionContainerEvent.java:40)

                                  at org.jboss.weld.bootstrap.events.ProcessManagedBeanImpl.fire(ProcessManagedBeanImpl.java:30)

                                  at org.jboss.weld.bootstrap.AbstractBeanDeployer.deploy(AbstractBeanDeployer.java:124)

                                  at org.jboss.weld.bootstrap.BeanDeployment.deployBeans(BeanDeployment.java:217)

                                  at org.jboss.weld.bootstrap.WeldBootstrap.deployBeans(WeldBootstrap.java:357)

                                  at org.jboss.as.weld.WeldStartService.start(WeldStartService.java:63)

                                  at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1811) [jboss-msc-1.0.4.GA-redhat-1.jar:1.0.4.GA-redhat-1]

                                  at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1746) [jboss-msc-1.0.4.GA-redhat-1.jar:1.0.4.GA-redhat-1]

                                  ... 3 more

                              • 12. Re: Classes in a WAR packaged inside an EAR are not visible to SwitchYard runtime
                                kcbabo

                                Sorry it's taken some time to get back with you.  I am able to reproduce this with the app you attached and I agree that the behavior is a bug.  Would you mind filing a JIRA?  The workaround at this point is what we discussed earlier in the thread - externalizing the interfaces from the WAR so they can be resolved by the EAR class loader.  This is not ideal, obviously, but at least it works.  The SY deployer likely needs to check if the sub-deployment is a WAR and act accordingly.