2

In a java web app, I need to call a remote soap service, and I'm trying to use a CXF 2.5.0-generated client. The soap service is provided by a particular ERP vendor, and its wsdl is monstrous, thousands of types, dozens of xsd imports, etc. wsdl2java generates the client ok, thanks to the -autoNameResolution flag. But at runtime it retrieves the remote wsdl twice, once when I create the service object, and again when I create a port object.

MyService_Service myService = new MyService_Service(giantWsdlUrl);  // fetches giantWsdl
MyService myPort = myService.getMyServicePort();  // fetches giantWsdl again

Why is that? I can understand retrieving it when creating myService, you want to see that it matches the client I'm currently using, or let a runtime wsdl location dictate the endpoint address, etc. But I don't understand why asking for the port would reload everything it just went out on the wire for. Am I missing something?

Since this is in a web application, and I can't be sure that myPort is threadsafe, then I'd have to create a port for each thread, except that's way too slow, 6 to 8 seconds thanks to the monstrous wsdl. Or add my own pooling, create a bunch in advance, and do check-outs and check-ins. Yuck.

For the record, the JaxWsProxyFactoryBean creation route does not ever fetch the wsdl, and that's good for my situation. It still takes a long time on the first create(), then about a quarter second on subsequent create()s, and even that's less than desirable. And I dunno... it sorta feels like I'm under the hood hotwiring the thing rather than turning the key. :)

Community
  • 1
  • 1
dave thompson
  • 133
  • 3
  • 9

1 Answers1

1

Well, you have actually answered the question yourself. Each time you invoke service.getPort() the WSDL is loaded from remote site and parsed. JaxWsProxyFactoryBean goes absolutely the same way, but once the proxy is obtained it is re-used for further invocations. That is why the 1st run is slow (because of "warming up"), but subsequent are fast.

And yes, JaxWsProxyFactoryBean is not thread-safe. Pooling client proxies is an option, but unfortunately will eat a lot of memory, as JAX-WS runtime model is not shared among client proxies; synchronization is perhaps better way to follow.

dma_k
  • 10,431
  • 16
  • 76
  • 128
  • What I was hoping to understand is *why* it fetches the wsdl every time a service object is created *and* every time a port object is created. If it's a bug, if it's something I'm not doing right, etc. It throws a real monkeywrench into my design. And using JaxWsProxyFactoryBean never fetches the remote wsdl, I don't pass it one, and it never requests the default. All I give it is an endpoint address. – dave thompson Feb 13 '12 at 17:05
  • Strange. Perhaps the way you create your service is not optimal. Try the following code: `MySEI sei = Service.getPort(MySEI.class);`. – dma_k Feb 13 '12 at 21:00