I am trying to create a #WebService with java 8 and jax-ws. However, I can't seem to find combination that will move the xmls "http://com.test.mymethod/mymethod" off of the envelope and onto the method. Instead every method I try adds it to the Envbelope and then puts ser: prefix before the MyWebmethod. (which would be good if I was creating and sending out wsdl but I have to match request format already in use elsewhere)
desired request format:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<MyWebmethod xmlns="http://com.test.mymethod/mymethod">
I think the only feasible way to to this (apart from asking: "Why is a semantically identical response not desired?" - but I am afraid of the answer :-) ) would be to "post-process" the response.
The obvious solution would be to define a SOAPHandlerfor the Service-Endpoint. This should be a straight-forward process:
Grab a sample response from your service (let's call this the "input XML" for the following steps).
Create a XSL Template to transform your input XML to the desired output form.
Annotate your #Webservice with a #HandlerChain annotation.
Create the handler chain .xml file to define your SOAP handler (there is a basic example of the whole process of defining handlers over at mkyong: http://www.mkyong.com/webservices/jax-ws/jax-ws-soap-handler-in-server-side/)
Use your XSLT from step 2 in the SOAP handler to transfrom the response's DOM.
That being said - I am not 100% positive that you will be able to sufficiently influence the output of the handler chain. There is a very real chance that the resulting textual representation after the application server has serialized your DOM is still non-satisfactory.
The second option would be to define a ServletFilterand have it rewrite the textual output of your webservice endpoint. That will most certainly give you complete control over the output form - but at the (significant) cost of regenerating a DOM to feed into you XSL template.
All in all: Why would you go through all the pain? I am seriously curious.
Related
Our Java proxy needs to communicate with a WCF based ESB/Service.
It looks like the service expects the XML payload to look like:
<xmlRequest><?xml version="1.0" encoding="UTF-8" standalone="yes"?><payload/></xmlRequest>
Is there anyway to slip this past SAAJ, so that the WCF service will get what it needs ?
Details
I know this is illegal, but their service is in production and I am trying to replace our DataPower appliance.
Our current security proxy, iteration #3, is DOM based.
As expected when I used XSLT to add the XML directive SAAJ indicated an error.
I have tried escaping the XML directive using :
CDATA to escape the XML directive.
CDATA to escape the entire payload.
Massaging the directive to look like valid XML
Using HTML escape characters.
Ws-Security is used: spring-ws + WSS4J so we can't modify the payload at the http level outbound once its been secured.
We modified spring-ws for a reasonable use case but I don't believe modifying wss4j for this special case would be maintainable.
Options
It looks like the most maintable option is to switch to simple CXF Stream based approach, with WSS4J.
Due diligance
This probably sounds familar but before I can move on to using CXF, management wants to be sure there is not a clever trick to escaping that XML directive.
Any comments including good natured chiding are welcome !
The part is a processing instruction. As per
https://www.w3.org/TR/REC-xml/#sec-pi and https://www.w3.org/TR/REC-xml/#sec-prolog-dtd you can see that the beginning of the document is a prolog, and for processing instructions during the document the PITarget may be anything BUT xml. So your document can no longer be parsed by a compliant parser.
If you believe the above is what the other side requires, try to serialize your document into a text node and add that as content of xmlRequest. It would looke like
<xmlRequest><?xml ...
Alternatively you could try to serialize your document into a CDATA section (https://www.w3.org/TR/REC-xml/#sec-cdata-sect) but for me it feels just similarly wrong as for you. And you already tried my suggestions.
After all the XMLdecl is optional (https://www.w3.org/TR/REC-xml/#NT-prolog). Have you tried to omit the xml declaration using this in your XSLT?
<xsl:output method="xml" omit-xml-declaration="yes" />
If all that does not work, how do other clients send the data? How do their messages look like?
I'm going to create one rest services in rest dsl xml. On that I have created one routes. For the route I am going to call my own microservices (this is created other project) for using toD uri. Once I get response I am going to take the values from the body (response json). After that again I am going to call other services in the same route based on the response values (we are taking one field in the response).
My question is
how we can take the values from the response in first service
And how to set headers in that respected values in first values..
How to call 2 services in route. Is it possible to call tod uri two times?
Sample code
<toD uri=http://localhost >
<log message =${body} >
(this response is going to set 2nd service query parameter value )
<toD uri=http://localhost? 1 services response values a>
Not sure if I fully understand your case, but here are my answers to your questions:
1) You can select any value from a JSON response with JsonPath. To use it later, you probably want to save it on the Message header
.setHeader("myHeader", jsonpath("$.your.json.path"))
2) Sorry, I don't understand this question :-)
3) Yes, you can make as many .to() or .toD() as you like
However, if you want to call REST services and you use the Camel REST component, you can profit from built-in URI templating. That means perhaps you don't need .toD()
For example
.to("rest:get:hello/{myHeader}")
would insert the value extracted from the JSON response above because the placeholder name is looked up in the message headers and if found replaced with the value of the corresponding message header
.setHeader("myHeader", jsonpath("$.your.json.path")) // assume jsonpath result is "world"
.to("rest:get:hello/{myHeader}") // URI "hello/world" is called
I'd like to log the original 'raw' request body (e.g. JSON) while using Camel Rest endpoints. What's the proper way to do this?
My setup (RouteBuilder) looks like this:
restConfiguration().component("jetty")
.host(this.host)
.port(this.port)
.contextPath(this.contextPath)
.bindingMode(RestBindingMode.json);
rest("myService/").post()
.produces("application/json; charset=UTF-8")
.type(MyServiceRequest.class)
.outType(MyServiceResponse.class)
.to(SERVICE_CONTEXT_IN);
from(SERVICE_CONTEXT_IN).process(this.serviceProcessor);
My problem here is that the mechanics such as storing the request as an Exchange property are 'too late' in terms of using this approach, any processors are too late in the route, i.e., the binding already took place and consumed the Request. Also the CamelHttpServletRequest's InputStream has already been read and contains no data.
The first place to use the log EIP is directly before the single processor:
from(SERVICE_CONTEXT_IN).log(LoggingLevel.INFO, "Request: ${in.body}")
.process(this.serviceProcessor);
but at that point the ${in.body} is already an instance of MyServiceRequest. The added log above simply yields Request: x.y.z.MyServiceRequest#12345678. What I'd like to log is the original JSON prior to being bound to a POJO.
There seems to be no built-in way of enabling logging of the 'raw' request in RestConfigurationDefinition nor RestDefinition.
I could get rid of the automatic JSON binding and manually read the HTTP Post request's InputStream, log and perform manual unmarshalling etc. in a dedicated processor but I would like to keep the built-in binding.
I agree there is no way to log the raw request (I assume you mean the payload going through the wire before any automatic binding) using Camel Rest endpoints.
But taking Roman Vottner into account, you may change your restConfiguration() as follows:
restConfiguration().component("jetty")
.host(this.host)
.port(this.port)
.componentProperty("handlers", "#yourLoggingHandler")
.contextPath(this.contextPath)
.bindingMode(RestBindingMode.json);
where your #yourLoggingHandler needs to be registered in your registry and implement org.eclipse.jetty.server.Handler. Please take a look at writing custom handlers at Jetty documentation http://www.eclipse.org/jetty/documentation/current/jetty-handlers.html#writing-custom-handlers.
In the end I 'solved' this by not using the REST DSL binding with a highly sophisticated processor for logging the payload:
restConfiguration().component("jetty")
.host(this.host)
.port(this.port)
.contextPath(this.contextPath);
rest("myService/").post()
.produces("application/json; charset=UTF-8")
.to(SERVICE_CONTEXT_IN);
from(SERVICE_CONTEXT_IN).process(this.requestLogProcessor)
.unmarshal()
.json(JsonLibrary.Jackson, MyServiceRequest.class)
.process(this.serviceProcessor)
.marshal()
.json(JsonLibrary.Jackson);
All the requestLogProcessor does is to read the in body as InputStream, get and log the String, and eventually pass it on.
You can solve this by:
Turning the RestBindingMode to off on your specific route and logging the incoming request string as is.
After which you can convert the JSON string to your IN type object using ObjectMapper.
At the end of the route convert the java object to JSON and put it in the exchange out body, as we turned off the RestBindingMode.
rest("myService/").post()
.bindingMode(RestBindingMode.off)
.to(SERVICE_CONTEXT_IN);
In my case, streamCaching did the trick because the Stream was readable only once. Thefore I was able log but was not able to forward the body any more. I hope this might be of help to someone
First off, I'm using an older version of Restlet (1.1).
Secondly, I'm not sure I'm doing the correct thing. Here's what I'm trying to do...
I'm creating a reporting service (resource). I'd like my service to listen for POST requests. The body of the request will contain the report definition. I'd like the response to be the CSV file generated by the service (the report). Is responding to a POST request in this manner OK from a REST standpoint (if not, then how to refine this resource)?
I can't seem to figure out how the acceptRepresentation() generates the response. I've tried setting the Representation parameter passed into the method to a new FileRepresentation. I've also tried to utilize the represent() method, but it doesn't seem like that method is called as part of the POST processing.
How can I accomplish this seeming easy task?
Calling the getResponse().setEntity() method from acceptRepresentation() will accept the new FileRepresentation and accomplish what I'd like to.
I am developing a Java application that makes an HTTP Request to a web service, and XML is returned. If the response code is 200, then a requestSucceeded() callback method will send the XML to a SAXParser with a different SAX Handler, depending on what web service is being called. If the response code is not 200, then a requestFailed() callback method is being called.
The web service that I am calling will return two types of XML documents (with a response code of 200): an XML document containing the successful response information, or an XML error document containing error information (for example, if one of the request parameters wasn't formatted correctly).
My question is this: Given my current setup, what is the best way to look for / handle both kinds of XML documents (a successful XML response or an XML error document)? The SAX Handler is looking for all of the relevant response information and it is storing that information into an object, which is then processed by my application. Is there a better solution than just always first looking for the unique XML Error tags?
Thanks!
Option #1 - Change Respose Code
Why are you returning an error with response code 200? 400 (Bad Request) or another error code might be a better option. Then you could process the XML based on the response code.
Option #2 - Swap Content Handlers
Below is a link to one of my previous answers where I explain how to swap content handlers while processing the document. You could have one content handler that determines if the response is content or error, and then swaps in the appropriate content handler to process the rest.
Using SAX to parse common XML elements
Option #3 - Use JAXB
If the end result is that the XML will be converted to an object, have you considered using JAXB? It will build an object based on the XML based on what is returned.