8 Replies Latest reply on Dec 14, 2011 9:02 AM by Richard Opalka

    JBossWS/CXF configuration / extensions

    Robert Stupp Newbie

      Hi,

       

      I am currently working on a project, where we need to add custom CXF interceptors to the CXF bus for the current deployment.

       

      The only practically working way to customize the deployment is to add a WEB-INF/jbossws-cxf.xml file to our deployment.

      Generally it works, but there are some bad things using the combination AS7/JBossWS/CXF.

       

      We have a lot of web services which are bundled in one or more WAR files.

      All of them have "standard" JAX-WS annotations (e.g. @WebService) and work fine (everything bundled in a WAR in an EAR ; deploy to AS7 ; fine).

       

      But as I mentioned, we need custom interceptors.

       

      So I added the interceptors to a jbossws-cxf.xml file:

          <jaxws:endpoint

                  address='http://@jboss.bind.address@/demo/service/SuperService'

                  implementor='com.mycompany.demo.java.MySuperWebservice'>

             <jaxws:inInterceptors>

                  <ref bean="myGreatInterceptor"/>

              <jaxws:inInterceptors>

          </jaxws:endpoint>

       

      This works - but what I really want is a default bus configuration for all webservices in the WAR file (deployment) - I do not want to configure all web services. So I tried the following approach in jbossws-cxf.xml:

          <bean class="com.mycompany.jboss7.cxf.BusInterceptorsInjector" init-method="injectInterceptors">

              <property name="bus" ref="cxf"/>

              <property name="inInterceptors">

                  <list>

                      <ref bean="FrameworkCxfPreInvokeInterceptor"/>

                      <ref bean="FrameworkCxfPostInvokeInterceptor"/>

                  </list>

              </property>

          </bean>

      This works - but only if every webservice is mentioned like

          <jaxws:endpoint

                  address='http://@jboss.bind.address@/demo/service/SuperService'

                  implementor='com.mycompany.demo.java.MySuperWebservice'/>

      This is silly, because the jaxws:endpoint configuration specifies nothing meaningful.

      Every invocation of a web service which is not mentioned in a jbossws-cxf.xml file, fails with a NullPointerException in org.jboss.wsf.stack.cxf.CXFInstanceProvider at line 57 - the CXFInstanceProvider is configured with a "null" ServerFactoryBean.

       

      What I would like to have in AS7/JBossWS/CXF is

      • a mechanism, where I can configure the CXF bus for each deployment (specifying another bus definition in jbossws-cxf.xml does not work, because the "default" bus is created "inside the server code") and
      • no need to specify every web service in jbossws-cxf.xml and
      • no need to specify the fully qualified address attribute in jaxws:endpoint - developers do not know the exact address, port and context path ot a deployment. AS7/JBossWS should accept at least paths relative to the context root of the current deployment (specifying addresses like /service/SuperService does not work - it cannot find the destination of a web service call)
      • no need to specify the implementor in jaxws:endpoint, because it is already configured elsewhere (web.xml) - a functionaltity like a "servlet-link" would be great

       

      Robert.

        • 1. Re: JBossWS/CXF configuration / extensions
          Robert Stupp Newbie

          Another issue is that the "address" attribute mentioned in jaxws:endpoint will be sent out in the generated WSDL - not good.

          • 2. Re: JBossWS/CXF configuration / extensions
            Alessio Soldano Master

            Hi Robert,

            thanks for the feedback, a lot of stuff to be discussed:

             

             

            This works - but only if every webservice is mentioned like

                <jaxws:endpoint

                        address='http://@jboss.bind.address@/demo/service/SuperService'

                        implementor='com.mycompany.demo.java.MySuperWebservice'/>

            This is silly, because the jaxws:endpoint configuration specifies nothing meaningful.

            It actually specifies that there's a jaxws endpoint with a given implementor.

             

             

            Every invocation of a web service which is not mentioned in a jbossws-cxf.xml file, fails with a NullPointerException in org.jboss.wsf.stack.cxf.CXFInstanceProvider at line 57 - the CXFInstanceProvider is configured with a "null" ServerFactoryBean.

            This is something to be improved, as that is basically hiding the actual source of the problem to the user, i.e. the jaxws endpoint has not been created in cxf bus. https://issues.jboss.org/browse/JBWS-3395

             

             

            What I would like to have in AS7/JBossWS/CXF is

            • a mechanism, where I can configure the CXF bus for each deployment (specifying another bus definition in jbossws-cxf.xml does not work, because the "default" bus is created "inside the server code") and

            A proposal here is to have a look at the endpoint configuration in the webservices domain of jboss AS7 and use @EndpointConfig(configFile=".." configName=".."). You can have any jaxws handler in the configuration and can also reference a configuration file in your deployment if you don't want to modify the AS7 domain.

             

            • no need to specify every web service in jbossws-cxf.xml and
            • no need to specify the fully qualified address attribute in jaxws:endpoint - developers do not know the exact address, port and context path ot a deployment. AS7/JBossWS should accept at least paths relative to the context root of the current deployment (specifying addresses like /service/SuperService does not work - it cannot find the destination of a web service call)
            • no need to specify the implementor in jaxws:endpoint, because it is already configured elsewhere (web.xml) - a functionaltity like a "servlet-link" would be great

            These are actually related. To be honest the web.xml is not mandatory, you might have @EJB endpoints in a jar archive. In any case, I see what you mean, we could have that info automatically derived from the metadata model that's produced from the info in web.xml/endpoint annotations.

            I've created a feature request for this: https://issues.jboss.org/browse/JBWS-3396

            To be honest, especially on AS7, we're suggesting users to go the non-spring approach with jbossws-cxf ws deployments (so in this case, use the @EndpointConfig approach), however this feature request is quite interesting and might be scheduled for JBWS 4.0.1.

            • 3. Re: JBossWS/CXF configuration / extensions
              Robert Stupp Newbie

              Hi Alessio,

               

              thanks for your answer and posting the requests for enhancements

               

              We have the situation, that we must support JBoss7 for new projects (but still have to support JBoss4 ).

              The same code has to work in JBoss7 and JBoss4 - so we cannot use "custom" annotations like @Endpoint.

               

              For JBoss7 I have used Spring wildcard bean names in jbossws-cxf.xml to "inject" my CXF invoker and interceptors.

              It was a bit hard to figure out that this works (a lot of debugging sessions ) - but it works great.

               

              The JAXWS handler does not work for us, because we need to intercept the Java reflection method call. We have to "replay" web service calls and therefore need to collect a lot of meta information.

               

              BTW: It would be nice to remove the "final" keywork from the org.jboss.ws.common.invocation.InvocationHandlerJAXWS and similiar classes - and from the org.jboss.ws.common.invocation.AbstractInvocationHandlerJSE.invoke() method - to allow users to override this functionality. I had to copy the code to my own implementations and could not reuse existing classes. Is it ok to open a new issue (RFE) in Jira?

               

              IMHO it is great to have app server specific annotations - but this means, that the application is bound to a specific app server and maybe specific app server configuration - means that the application is not portable. There should be an alternative to be able to keep the code portable.

              • 4. Re: JBossWS/CXF configuration / extensions
                Alessio Soldano Master

                Hi Robert,

                We have the situation, that we must support JBoss7 for new projects (but still have to support JBoss4 ).

                The same code has to work in JBoss7 and JBoss4 - so we cannot use "custom" annotations like @Endpoint.

                I see... generally speaking this is going to be quite an issue, as JBoss AS7 is a major change in pretty much all area (and similarly there's no jbossws stack running on both JBoss 4 and 7). So I understand you're doing some kind of advanced hacking with the ws stack... unfortunately that's a bit beyond what we'd usually support, however reasonable needs/requests are still considered:

                BTW: It would be nice to remove the "final" keywork from the org.jboss.ws.common.invocation.InvocationHandlerJAXWS and similiar classes - and from the org.jboss.ws.common.invocation.AbstractInvocationHandlerJSE.invoke() method - to allow users to override this functionality. I had to copy the code to my own implementations and could not reuse existing classes. Is it ok to open a new issue (RFE) in Jira?

                Yes, we can consider this. Please create a jira and provide a basic description of an example of extension that would need those changes.

                 

                IMHO it is great to have app server specific annotations - but this means, that the application is bound to a specific app server and maybe specific app server configuration - means that the application is not portable. There should be an alternative to be able to keep the code portable.

                The @EndpointConfig is not an app server specific annotation to be honest. It comes from JBossWS and has been introduced in JBossWS 4. To be honest an equivalent annotation was there for jbossws native since years, with the 4 major release that's being converted in a stack independent new annotation. That will be available on all app server the JBossWS 4 series will support as target containers.

                In theory, you have *real* portability as long as you only leverage standards / specification APIs. Anything else, any additional feature usage (being that from JBoss AS, JBossWS, Apache CXF, etc.) is likely to break portability, depending on which are your target containers.

                • 5. Re: JBossWS/CXF configuration / extensions
                  Robert Stupp Newbie

                  Hi Alessio,

                   

                  Sorry - I got confused with the annotation org.jboss.ws.api.annotation.EndpointConfig and class org.jboss.wsf.spi.metadata.config.EndpointConfig.

                   

                  Yes, I am hacking deep in JBossWS with CXF on AS7 and (hopefully) on AS4. It is not easy to dig through and undestand the code, but I understand how JAXWS/RPC invocation works.

                  This is maybe nothing, what most developers do with JBossWS

                   

                  BTW: I like AS7.1 - its speed and modularity

                  • 6. Re: JBossWS/CXF configuration / extensions
                    Richard Opalka Master

                    Robert Stupp wrote:

                     

                    BTW: It would be nice to remove the "final" keywork from the org.jboss.ws.common.invocation.InvocationHandlerJAXWS and similiar classes - and from the org.jboss.ws.common.invocation.AbstractInvocationHandlerJSE.invoke() method - to allow users to override this functionality. I had to copy the code to my own implementations and could not reuse existing classes. Is it ok to open a new issue (RFE) in Jira?

                    We're not going to remove "final" keywords but I have a workaround description for you instead

                    I see U're dealing with JBossWS internals so the following workaround might be acceptable for you:

                     

                    * implement your own version of org.jboss.wsf.spi.invocation.InvocationHandlerFactory (for inspiration see org.jboss.as.webservices.invocation.InvocationHandlerFactoryImpl)

                    * your implementation will register your own delegating invocation handlers

                    * your every invocation handler will contain JBossWS specific handler as delegate and it will delegate all calls to it (http://en.wikipedia.org/wiki/Adapter_pattern)

                    * around these delegating calls you can implement your own monitoring/logging code

                     

                    Feel free to ask further questions if something is not clear.

                    • 7. Re: JBossWS/CXF configuration / extensions
                      Robert Stupp Newbie

                      Hi Richard,

                       

                      I tried to create my own implementation of the InvocationHandlerFactory - but unfortunately it is impossible to use a custom implementation in AS7 , because there is just one InvocationHandlerFactory (org.jboss.as.webservices.invocation.InvocationHandlerFactoryImpl from jboss-as-webserver-integration). AS7 webservice integreation uses its own factory - only its own factory.

                      That's the reason why I made such a complicated approach.

                      • 8. Re: JBossWS/CXF configuration / extensions
                        Richard Opalka Master

                        Well U need to delete /META-INF/services/org.jboss.wsf.spi.invocation.InvocationHandlerFactory from

                        $JBOSS_HOME/modules/org/jboss/as/webservices/main/jboss-as-webservices-server-integration*.jar

                        Then provide your own jar containing your InvocationHandlerFactoryImpl and place it in

                        $JBOSS_HOME/modules/org/jboss/as/webservices/main folder

                        (including /META-INF/services/org.jboss.wsf.spi.invocation.InvocationHandlerFactory definition)

                        plus update $JBOSS_HOME/modules/org/jboss/as/webservices/main/module.xml accordingly.