How to get control over JAXBContext in JAX-WS?

I need to deploy the same web service for each client. This @javax.jws.WebService uses Object as method arguments and return types (as a result of <xs:anyType/> in wsdl). Each web service instance is deployed along with the client’s bank on the class path. This banner has a well-known structure and contains JAXB-annotated classes that the client wants to process through my service.

The problem is that when a client passes an instance of its class as an agrument method, the server-side JAXB context cancels it in some weird xerces dom node, because (as far as I understand) only @WebMethod and @WebService were scanned during deployment annotations that, as already mentioned, deal only with Object .

Simply put, I need to hint JAXB to WEB-INF/lib/customer_classes_14586.jar , which means some control over the creation of JAXBContext during the deployment of JAX-WS.

Is it possible at all?

Server-specific solutions are great (Glassfish 3.1 with meto ws stack)

UPDATE

I missed one thing that may be important: I deploy these web services as OSGI packages at runtime through the web admin console. When I press the deploy button, a new bank is programmatically created from the client library, webservice, wsdl class and appears. That way, I could intervene in the build process and provide a hint of information at this point in time, if that helps.

+6
source share
2 answers

The first option is the @UsesJAXBContext annotation. Read more here: Specify JAXB Packages in SLSB and JAX-WS

I did not test it when I found this annotation; I am already halfway to another solution that may be useful to others.

The key uses @WebServiceProvider instead of @WebService , a bit low-level but simple:

 @WebServiceProvider( wsdlLocation = "WEB-INF/wsdl/injector.wsdl" ) @ServiceMode(value = Service.Mode.PAYLOAD) public class InjectorService implements Provider<Source> { private Unmarshaller unmarshaller; @Override public Source invoke(Source request) { try { DOMResult requestDom = new DOMResult(); Transformer trans = TransformerFactory.newInstance().newTransformer(); trans.transform(request, requestDom); Node requestNode = requestDom.getNode(); // Get the operation name node. Node operationNode = requestNode.getFirstChild(); // Get the parameter node. Node parameterNode = operationNode.getFirstChild(); // Unmarshal JAXBElement<Object> element = unmarshaller.unmarshal(parameterNode, Object.class); Object unmarshalled = element.getValue(); // Handling customer object and response ...... } catch (Exception e) { throw new RuntimeException("Endpoint error", e); } } protected Class[] getCustomerClasses() { // return customer classes somehow } @PostConstruct public void init() throws Exception { JAXBContext jbc = JAXBContext.newInstance(getCustomerClasses()); unmarshaller = jbc.createUnmarshaller(); } } 

What is it. Client classes can be derived from a class, package context, or any other.

+4
source

From what I know, there is no “declarative” way of hinting at an alternative way to unleash, other than the one you already have on JAX-WS or JAXB — what you are looking for. By the way, the "weird" Xerces node is really expected, since xsd: any / anyType and Object go hand in hand in your script.

My suggestion is to use a relatively simple and portable solution: create your own thin layer of “bindings” inside your common web method. All he does for the incoming is to make the unmarshalling XML node a Java class according to your other JAXB bindings. Then it should look up the name of the Java package (for your JAXBContext) from the QName of the DOM element not exposed to the token of your WS stack. A search can use a properties file, reflection, or any other mechanism specific to your deployment. For outbound (return), you then use the reverse logic to sort the response. This approach is actually quite common, especially when other types of unsupported XML binding technologies are tunneled through the standard WS stack.

+2
source

Source: https://habr.com/ru/post/896605/


All Articles