Java – JBoss 4.2.2 web service soap:address

javajbossweb services

I have an EJB3 bean deployed as a web service in JBoss 4.2.2. In production the server is behind an Apache server that redirects requests to the Jboss server. This makes the WSDL have the wrong soap:address location. I was able to get the port and host name changed via the configuration file in server\default\deploy\jbossws.sar\jbossws.beans\META-INF, but I haven't been able to get it to switch the protocol to https.

The only way that I found was to specify my own WSDL (via here). By specifying https in the WSDL, JBoss picks up that it is https. However, although that is fine in production, in QA https is not used (and the service that connects to it requires valid https, so self-signed certificates won't do). So while I could get a real certificate for QA (fake certificate authorities won't do), I would rather have it be http in QA. Is there a way to force JBoss to change the protocol or otherwise change the address so that it uses http in the soap:address?

EDIT: It seems like this issue was brought up recently in their bug database and was rejected. That would imply to me that they have a work around. But what is it?

Further EDIT: At this point, I know that an EJB3 Interceptor doesn't work (they are not activated at all) and SOAPHandler's don't intercept the call to retrieve the WSDL (tested – they pick up everything else). So the filter idea is intriguing, but it is far from clear where to put it.

The URL as shown by JBoss is:

Endpoint Name jboss.ws:context=QuickBooks-QuickBooksWebService,endpoint=QBWSBeanEJB
Endpoint Address https://127.0.0.1:8443/QuickBooks-QuickBooksWebService/QBWSBeanEJB?wsdl

(Note that is when I use the custom WSDL to force https but JBoss is configured to rewrite it).

The version of JBossWS I'm using is what is bundled with 4.2.2, which according to this is 2.0.1

EDIT: With regards to the rewriting, this was indeed attempted. Here is what I found. I could get it to rewrite the host (or not as needed) and the port, but only for the recognized protocol. So in order to get it emit an https, I had to configure the bean's transport guarantee to CONFIDENTIAL, and enable https on the JBoss server, then all requests were redirected to https within JBoss. I didn't test if this would even work with mod_jk (does the AJP protocol still work if CONFIDENTIAL is required, and will the WSDL get the right protocol if the request comes over AJP? I didn't test it), however doing that has the same net effect – the requests must go over https. There is no way to have the request come in over http or AJP and then have it emit a soap:address as https, specifically configured on a per-server basis (in QA and dev, http, in but in production https even though the ssl was terminated by Apache). Using the custom WSDL got me closer, in that the request is coming in on HTTP, but the soap:address says https. Perfect for production (using the rewrite feature to push the port to 443 instead of 8443), but useless for QA (dev I don't care about, because the dev build could be different and create a different jar if needed, but I'm not comfortable with QA and production having different build processes if I can avoid it).

Best Answer

Why don't you set up a servlet filter on your web application which watches for WSDL requests and rewrites the soap:address in the responses using values from its configuration? Then you can set it up however you want.

It may not be the most elegant solution, I agree :-) - but then that would have been for the configurability to be in JBoss, wouldn't it? And if JBoss eventually introduces this feature, you can just remove the filter.

Update: A typical JBoss EAR has the following structure:

myapp.ear
|+ META-INF
   |+ applications.xml and jboss-app.xml
|+ myapp.war
   |+ web pages and JSP /JSF pages
   |+ WEB-INF
      |+ web.xml, jboss-web.xml, faces-config.xml etc.
      |+ lib
         |+ tag library JARs
      |+ classes
         |+ servlets and other classes used by web pages
|+ myapp.jar
   |+ EJB3 bean classes
   |+ META-INF
      |+ ejb-jar.xml and persistence.xml
|+ lib
   |+ Library JARs for the EAR

Can you confirm that your deployed EAR has this structure? If not, how is it different?

Update #2: JBoss automatically generates a web.xml for EJB3 beans which are in a JAR inside the EAR being deployed. This web.xml is definitely hard-coded (i.e. doesn't use as a basis an XML file which you can tweak) and so it is awkward (though not impossible) to change this to include a filter (you basically need to change various things in jboss-beans.xml to point to your own web.xml generator, which can do whatever you want). It would be a lot less development work if the EJB3 beans were in the WAR file - then you can configure the Filter conventionally using the WAR's web.xml, which you presumably have control over. However, that might be problematic if that's a third-party JAR you're using - or it might not. Without knowing the details it's hard to see which the best approach will be.


Edit from the question's author:

Thanks for all the effort. This appears to be the basic approach - intercept and change the WSDL. If you can't make your webservice a POJO assigned in the war, where you can use a servlet filter, then you can make a servlet that proxies the request, and do it that way. That was my solution.