I'm trying to alter a message using a custom class mediator in wso2 esb. What I'm trying to achieve is to add/set the value of an element in the message sent. The message is sent using a REST API, and it goes through the mentioned class (where the transformation happens). However, when I do a full log of the message after the class, I see that the message keeps the same values that had at first (basically the class only alters the message while it's in the class mediator, so when it comes out of the mediator, it goes back to its original input form).
Input:
Body : <soapenv:Body ...><jsonObject><ts>2020-01-13</ts><temp></temp></jsonObject></soapenv:Body>
Desired output:
Body : <soapenv:Body ...><jsonObject><ts>2020-01-13</ts><temp>Hello</temp></jsonObject></soapenv:Body>
Things that I've tried so far and that didn't work:
Get message context, get the desired element and set the text
Use a OMFactory to create an OMElement and put that new element in the message context
Get the new altered envelope and set it as the new message context envelope
Create a new json payload
Any idea of how to get it working ?
You can refer to the following logic which changes the payload
#Override
public boolean mediate(MessageContext messageContext) {
try {
org.apache.axis2.context.MessageContext axis2MessageContext = ((Axis2MessageContext)messageContext).getAxis2MessageContext();
JSONObject jsonBody = new JSONObject();
JSONObject jsonError = new JSONObject();
jsonError.put("error","Authoraization Missing");
jsonError.put("detail","Authoraization Credentials invalid");
jsonError.put("title","Authoraization Error");
jsonBody.put("status", "403");
jsonBody.put("errorMessage", jsonError);
String transformedJson = jsonBody.toString();
JsonUtil.newJsonPayload(axis2MessageContext,transformedJson, true, true);
// change the response type to XML
axis2MessageContext.setProperty("messageType", "application/xml");
axis2MessageContext.setProperty("ContentType", "application/xml");
} catch (Exception e) {
System.err.println("Error: " + e);
return false;
}
return true;
}
If this doesn't help, kindly share your code to have an idea.
I already tried that tutorial #Nirothipan, but didn't work.
My code:
#Override
public boolean mediate(MessageContext mc){
String measure = mc.getEnvelope().getBody().getFirstElement().getFirstChildWithName(new QName("measure")).getText();
mc.getEnvelope().getBody().getFirstElement().getFirstChildWithName(new QName("temp")).setText(measure);
return true;
}
Should be more than enough to modify that element value imo.
Related
I am currently working with the Restlets framework, and I cannot find a way to manually set the HTTP response code within a service method. Consider the following snippet of code:
public class MyResource extends ServerResource {
#Post("json")
public Representation doSomething(Representation entity) throws IOException {
int status = 200;
try {
// do something which might throw an exception
}
catch (Exception e) {
// log the exception
// *** I would like to assign HTTP status 500 here ***
status = 500;
}
JSONObject responseJSON = new JSONObject();
responseJSON.put("result", "some data");
Representation rep = new JsonRepresentation(responseJSON.toJSONString());
return rep;
}
}
I have the ability to catch and log an exception, should one occur, but it is not clear how I can change the HTTP response code. As far as I know, returning from doSomething will automatically be handled by Restlets with an 200 HTTP response code.
I know how to assign the status code directly from a filter or servlet, but is it possible to do this within Restlets, without going down the servlet layer?
As far as I know, there is an object called ResponseEntity which you can use to operate with microservices and a request-response programming model, which allows you to specify the returning HTTP return code. However, you need entities for this, and I think this goes below your abstraction level of Servlets.
You can change them to some predefined values such as HTTP.INTERNAL_SERVER_ERROR and such, which translate to a value in the end, which you can Google in the end.
I hope this was of some help
EDIT:
Import the necessary resource for a ResponseEntity object. In STS, it is
import org.springframework.http.ReponseEntity;
import org.springframework.http.HttpStatus;
public class MyResource extends ServerResource {
#Post("json")
public ResponseEntity<Representation> doSomething(Representation entity) throws IOException {
int status = 200;
try {
// do something which might throw an exception
}
catch (Exception e) {
ResponseEntity<Representation> response = null;
response = new ResponseEntity<Representation>(HttpStatus.INTERNAL_SERVER_ERROR);
return response;
}
JSONObject responseJSON = new JSONObject();
responseJSON.put("result", "some data");
Representation rep = new JsonRepresentation(responseJSON.toJSONString());
return rep;
}
And sorry for the delay. I am new to Stack Overflow
I'm using ResteasyClient to make a REST client to my another service A. Say, service A throws an exception CustomException with a message : Got Invalid request.
Here is how I am using the Client:
public Response callServiceA(final String query) {
ResteasyClient client = new ResteasyClientBuilder().build();
String link = "abc.com/serviceA";
ResteasyWebTarget target = client.target(link).path("call");
Form form = new Form();
form.param("query", query);
Response response;
try {
String data =
target.request(MediaType.APPLICATION_JSON_TYPE)
.post(Entity.entity(form,
MediaType.APPLICATION_FORM_URLENCODED_TYPE),
String.class);
response = Response.ok().entity(data).build();
} catch (Exception e) {
String message = e.getMessage();
e.printStackTrace();
response = Response.serverError().entity(e.getMessage()).build();
} finally{
client.close();
}
return response;
}
However, when I print the stacktrace, I'm unable to find my custom error message. I can just see the message as HTTP 400 Bad Request.
Could you please suggest me how to access the error message?
NOTE: I am able to get the error message when I call the serviceA using the restClient. Hence, I dont think there is an issue with the service.
Don't deserialize the response straight to a String.
String data = ...
.post(Entity.entity(form,
MediaType.APPLICATION_FORM_URLENCODED_TYPE),
String.class);
When you do this (and there is a problem), you just get a client side exception, which doesn't carry information about the response. Instead just get the Response with the overloaded post method
Response response = ...
.post(Entity.entity(form,
MediaType.APPLICATION_FORM_URLENCODED_TYPE));
Then you can get details from the Response, like the status and such. You can get the body with response.readEntity(String.class). This way you don't need to handle any exceptions. Just handle conditions based on the status.
Do note though that the Response above is an inbound Response, which is different from the outbound Response in your current code. So just make sure not to try and send out an inbound Response.
Also see this answer and it's comments for some design ideas.
According to : PlayFramework Document 2.0 & PlayFramework Document 2.1
I know that in play I can return:
Ok()
badRequest()
created()
status()
forbidden()
internalServerError()
TODO
etc...
I would like to send with ajax an response with my information in it. Unfortunatelly play sends only status information, and some kind of object which I do not understand.
Only method ok("Test message") sends status and my message information. Rest of it dosnt work.
How to deal with it?
-- Edit --
I have ajax method:
$.post($("#assignmentsubmitAddress").text(), { 'units' : submittedUnits },
function(response, status, xhr) {
showNotyfication(status, response);
})
When I return ok("test");
In java script variable response I have just String test
When I return badRequest("test"); In java script variable response I have java object. When I print variable response I am getting Object object.
To send back a response in the json format to your client send a ok containing a string :
/**
* Translate a json object into a json string.
*/
public static<T> String objToJson(Object obj)
{
ObjectMapper mapper = new ObjectMapper();
try{
String json = mapper.writeValueAsString(obj);
return json;
}catch(java.io.IOException e){
Logger.error(e.getMessage(), e);
}
return "";
}
public static Result actions()
{
Object objToSendBack = ...
return ok(objToJson(objToSendBack));
}
You can send back wathever you want, including html, but json is more convenient for communicating with javascript functions.
I've figure it out.
I've just changed variable response which is an object to response.responseText.
Now it works.
I've found a read a number of threads on here about how to retrieve the XML response from a JAX-WS client. In my case, the client is generated from the WSDL via Oracle's JDeveloper product and is going to invoke a Document/Literal service endpoint that was written in .NET. What I want to do is obtain the XML response from the call FROM the calling client, not from inside a handler.
The closest thread that I saw to this issue was:
http://www.coderanch.com/t/453537/Web-Services/java/capture-SoapRequest-xml-SoapResponse-xml
I don't think I want to generate a Dispatch call because the endpoint's XML schema for the SOAP packet is rather complex, and the automatic proxy makes the call trivial. Unless there is some other way to populate the generated bean(s) and then invoke some method that simply produces the XML and I then make the call?
private void storeSOAPMessageXml(SOAPMessageContext messageContext) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
SOAPMessage soapMessage = messageContext.getMessage();
try {
soapMessage.writeTo(baos);
String responseXml = baos.toString();
log.debug("Response: " + responseXml );
PaymentGatewayXMLThreadLocal.set(responseXml);
} catch (SOAPException e) {
log.error("Unable to retrieve SOAP Response message.", e);
} catch (IOException e) {
log.error("Unable to retrieve SOAP Response message.", e);
}
}
My thought was to store the response to the call in a ThreadLocal inside the handler and then read it after the call. Is that reasonable? So after the handler does the above code in the handleMessage and handleFault, the client calling code invokes this method:
#Override
public String getSOAPResponseXML(Object clientstub) {
String returnValue = PaymentGatewayXMLThreadLocal.get();
return returnValue;
} // getSOAPResponseXML
It appears there may be another way after all. After reading jax-ws-handlers, I saw that the handler can introduce an Application scoped variable. I changed the handler to do this:
private void storeSOAPMessageXml(SOAPMessageContext messageContext) {
String xml = getSOAPMessageXml(messageContext);
// YourPayXMLThreadLocal.set(xml);
// put it into the messageContext as well, but change scope
// default of handler Scope, and client can't read it from responsecontext!
messageContext.put(SOAP_RESPONSE_XML, xml);
messageContext.setScope(SOAP_RESPONSE_XML, MessageContext.Scope.APPLICATION );
} // storeSOAPMessageXml
The client just reads it like this:
#Override
public String getSOAPResponseXML(Object clientstub) {
String returnValue = null;
// works (assuming a threadlocal is ok)
// returnValue = YourPayXMLThreadLocal.get();
BindingProvider bindingProvider = (BindingProvider) clientstub;
// Thought this would work, but it doesn't - it returns null.
// Map<String, Object> requestContext = bindingProvider.getRequestContext();
// String returnValue = (String) requestContext.get(JaxWsClientResponseXmlHandler.SOAP_RESPONSE_XML);
// this works!!
Map<String, Object> responseContext = bindingProvider.getResponseContext();
System.out.println("has key? " + responseContext.containsKey(JaxWsClientResponseXmlHandler.SOAP_RESPONSE_XML));
returnValue = (String) responseContext.get(JaxWsClientResponseXmlHandler.SOAP_RESPONSE_XML);
return returnValue;
} // getSOAPResponseXML
If you just want to see the request, you can use the system property
-Dcom.sun.xml.ws.transport.http.client.HttpTransportPipe.dump=true
If you actually want to do something with the request, then a handler seems the natural solution. Perhaps use the request context to pass values to the handler? On the client:
((BindingProvider) port).getRequestContext().put("KEY", "VALUE");
In the handler:
String value = (String) messageContext.get("KEY");
Unfortunately, the only way to get the XML before sending it and without using Message Handlers is to marshall it your self (see JAXB). This will give you an XML representation of the data, however it might not LOOK exactly the same as the message sent to the WS. Differences might arise in the way that namespaces are used, ect., but most importantly you will not get the whole SOAP envelope, just the XML data for the header you choose to marshall.
I am writing a java axis client, how could I persist raw xml into data base, till now I have found two ways of logging raw xml, but they are for console or to a file, but I need to persist each request and response into mysql database, where I could use connection as a user parameter.
here is what I have done already.
log raw ws xml to console
log raw ws xml to a file
Well I have found a solution, First we need to use the Custom handler as I mentioned earlier(1), we can set property in the message context
like
public class FedexWsHandler extends GenericHandler {
public QName[] getHeaders() {
return null;
}
public boolean handleRequest(MessageContext context) {
try {
SOAPMessageContext smc = (SOAPMessageContext) context;
SOAPMessage reqMsg = smc.getMessage();
context.setProperty("req-msg", reqMsg);
} catch (Exception ex) {
ex.printStackTrace();
}
return true;
}
public boolean handleResponse(MessageContext context) {
try {
SOAPMessageContext smc = (SOAPMessageContext) context;
SOAPMessage reqMsg = smc.getMessage();
context.setProperty("res-msg", reqMsg);
} catch (Exception ex) {
ex.printStackTrace();
}
return true;
}
}
and then in out client we can get that property and do what ever you want to do, like
MyServiceLocator locator = new MyServiceLocator();
MyService service = locator.getMyService();
service.getResults("foo", "bar"); // call the service
// I want to get that message I have set in request and response handler methods
MessageContext ctx = locator.getCall().getMessageContext();
SOAPMessage reqMsg = (SOAPMessage) requestContext.getProperty("req-msg");
SOAPMessage resMsg = (SOAPMessage) requestContext.getProperty("res-msg");
But it is not a safe way to do that as this is not Thread Safe. as per its docs
.... so if any one can suggest me some better solution.
JAXB Marshaller : StringWriter output has a truncated tag value
Please have a look on the above post, you can convert the xml to java string and and than you can use any mysql data type which can hold your xml converted to string. you can use blob if the string in very large.