How to transform java object to XML with axis 1.4? - java

We are using axis 1.4 for our WS implementation.
Whenever the WS request fails we would like to add to our logging the XML of the actual request that was sent.
To do that we of course need to be able to transform the request object into its XML representation, same as it will be sent later to the server.
In most cases this is to be able later copy-paste it to some other tool, for debug, so it is important to have exactly same XML string as it would be sent to the server.
Hope that was clear enough.
Thank you.

OK, answering my own question:
To do so for Axis-1.4, according to the example posted by NJSC, need to replace SerializationContextImpl with just a org.apache.axis.encoding.SerializationContext.
qname = removeNamespaces ? new QName(lname) : new QName(qname.getNamespaceURI(), lname);
final AxisServer server = new AxisServer();
final BeanSerializer ser = new BeanSerializer(obj.getClass(), qname, typeDesc);
final SerializationContext ctx = new SerializationContext(outStr, new MessageContext(server));
ctx.setSendDecl(false);
ctx.setDoMultiRefs(false);
ctx.setPretty(prettyPrint);

Related

How to convert soap response to string in java?

I am using WebServiceTemplate to consume SOAP response. For logging purpose i need to get the SOAP response in string.
For example , "<envelope><body><name>xyz</name></body></envelope>"
You can achive it like below with WebServiceTemplate:
ByteArrayOutputStream bytArrayOutputStream = new ByteArrayOutputStream();
StreamResult result = new StreamResult(bytArrayOutputStream);
wsTemplate.sendSourceAndReceiveToResult(defautUri, source, result);
final String reply = new String(bytArrayOutputStream.toByteArray())
If you using spring, you can add log using log4j in interceptor. Log4j can write to file or even db. I hope its help you.

Get EC2 Instance XML Description using AWS Java SDK?

We have a scenario in which we need to retrieve the description info for EC2 instances running on AWS. To accomplish this, we are using the AWS Java SDK. In 90% of our use case, the com.amazonaws.services.ec2.model.Instance class is exactly what we need. However, there is also a small use-case where it would be beneficial to get the raw XML describing the instance. That is, the XML data before it is converted into the Instance object. Is there any way to obtain both the Instance object and the XML string using the AWS Java SDK? Is there a way to manually convert from one to the other? Or, would we be forced to make a separate call using HttpClient or something similar to get the XML data?
Make an EC2Client by adding request handler and override the beforeUnmarshalling() method like below
AmazonEC2ClientBuilder.standard().withRegion("us-east-1")
.withRequestHandlers(
new RequestHandler2() {
#Override
public HttpResponse beforeUnmarshalling(Request<?> request, HttpResponse httpResponse) {
// httpResponse.getContent() is the raw xml response from AWS
// you either save it to a file or to a XML document
return new HTTPResponse(...);
// if you consumed httpResponse.getContent(), you need to provide new HTTPResponse
}
}
).build():
If you have xml (e.g. from using AWS rest API directly), then you can use com.amazonaws.services.ec2.model.transform.* classes to convert xml to java objects. Unfortunately, it only provides classes required for SDK itself. So you, for example, can convert raw XML to an Instance using InstanceStaxUnmarshaller, but can't convert Instance to XML unless you write such converter.
Here is an example how to parse an Instance XML:
XMLEventReader eventReader = XMLInputFactory.newInstance().createXMLEventReader(new StringReader(instanceXml));
StaxUnmarshallerContext suc = new StaxUnmarshallerContext(eventReader, new TreeMap<>());
InstanceStaxUnmarshaller isu = new InstanceStaxUnmarshaller();
Instance i = isu.unmarshall(suc);
System.out.println(i.toString());
You probably can try to intercept raw AWS response, so that you can keep raw XML while still using SDK most of the time. But I wouldn't call that easy as it will require quite a bit of coding.
You could use JAXB.marshal like following. JAXB (Java Architecture for XML Binding) could convert Java object to / from XML file.
StringWriter sw = new StringWriter();
JAXB.marshal(instance, sw);
String xmlString = sw.toString();
You can use AWS rest API to replace Java SDK. A bonus will be slight performance gain because you'll not send statistic data to Amazon as the SDK does.

Apache camel simple http example

I am pretty new with Camel. I have been trying to fetch a data from http source.
Here's my code:
from("timer://runOnce?repeatCount=1")
.to("http4://webservice.com/example.xml")
.process(new structureXML())
.to("mock:resource")
.stop();
And:
class structureXML implements Processor {
public void process(Exchange httpExchange) throws Exception {
String httpres = httpExchange.getIn().getBody(String.class);
String[] lines = httpres.split("\n");
Pattern p = Pattern.compile("<Map Key='(.+)' Value='(.+)'/>");
HashMap<String, Integer> mapdata = new HashMap<String, Integer>();
for(String line : lines) {
Matcher m = p.matcher(line);
if(m.find())
mapdata.put(m.group(1), Integer.parseInt(m.group(2)));
}
httpExchange.getIn().setBody(mapdata);
}
}
Well the example works right but I want to know about the possible ways to further improve this situation(e.g xml processing using xpath and etc), also I want to know about the ways which I can store the java object inside the message so I can use it in another route(e.g: direct:resource instead of mock)
About java objects:
More information can be found here: http://camel.apache.org/data-format.html
JAXB
XStream
BeanIO
JiBX
XmlBeans
These data formats will be very useful for transforming XML to POJO.
I recomend you to try BeanIO (detailed documentation, many examples, etc).
About Xpath:
it's hard to tell anything specified without web-service response.
Example:
setBody().xpath("/soap:Envelope/soap:Body/s:insertResponse/s:data",
XmlNamespaces.getNamespace()).
About your example:
You usually need to set a lot of properties and header (before http request), so it worked fine. Example:
setProperty(Exchange.CONTENT_TYPE).constant("application/soap+xml").
setProperty(Exchange.CONTENT_ENCODING).constant("gzip").
setProperty(Exchange.CHARSET_NAME).constant("utf-8").
setHeader(Exchange.CONTENT_TYPE).exchangeProperty(Exchange.CONTENT_TYPE).
And I don't see creating the request to web-service. It is easy to do with the help of velocity (http://camel.apache.org/velocity.html), or, maybe, using SOAP date format (http://camel.apache.org/soap.html).
You can use jetty (http://camel.apache.org/jetty.html) instead of http4 (for me it's easier)

XStream not sent via sockets

I used already working code for save/load game for sending a player state via sockets. And I encountered a problem that game save is correct, but server is not receiving client's player state.
Here is the base code that is tested and working:
int retval = fc.showSaveDialog(givenComponent);
if (retval == JFileChooser.APPROVE_OPTION) {
File file = fc.getSelectedFile();
try {
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF-8"));
XStream xs = new XStream();
GameSave gs = new GameSave();
ArrayList<PlayerSerialize> listps = new ArrayList<PlayerSerialize>();
for (Player tempplayer : Players.players) {
PlayerSerialize ps = new PlayerSerialize();
ps.getPlayerData(tempplayer);
listps.add(ps);
}
gs.playersSerialize = listps;
gs.gamedate = Dateutils.gamedate;
String s = xs.toXML(gs);
bw.write(s);
bw.close();
} catch (IOException ex) {
Logger.getLogger(DialogMainField.class.getName()).log(Level.SEVERE, null, ex);
}
}
Here is the client side code that is not sending anything to server:
XStream xs = new XStream();
GameSave gs = new GameSave();
ArrayList<PlayerSerialize> listps = new ArrayList<PlayerSerialize>();
PlayerSerialize ps = new PlayerSerialize();
ps.getPlayerData(Players.players.get(1));
listps.add(ps);
gs.playersSerialize = listps;
gs.gamedate = Dateutils.gamedate;
String s = xs.toXML(gs);
out.println("clientplayertoserver");
out.println(s);
Here is the server side just in case:
if (strIn.contains("clientplayertoserver")) {
strIn = in.readLine();
XStream xs = new XStream();
GameSave gs = (GameSave) xs.fromXML(strIn);
Players.players.get(1).getPlayerSerializeData(gs.playersSerialize.get(0));
}
I need some kind of clue because I'm stuck investigating the problem. Are there any XStream limitations? Or the error is in the working with sockets? The same code is working in one place and is not working in another - I greatly thank in advance for any help with this weird situation.
Well, you are doing two different things here:
1) Saving the data to a file, which is ok.
2) Sending data via a socket. You seem to assume that all your data (the XStream serialized object) is actually in one line. This will usually not be the case. Even if you configure XStream to serialize all data without identation, you still cannot be sure you won't have linebreaks in the serialized data (your variables).
So solve your issue, you should separate your concerns here.
1st serialize / deserialize your objects to String and back (that seems to be working for you.
2nd send this data to a medium, like a file (which you already have) or to a server.
For sending string data to a server, you'll need some kind of protocol. Either you can reuse an existing protocol, like HTTP (POST request to a server), Web Service, Rest Call or whatever else your server is running.
If you want to implement your own protocol (as you have tried above), you must ensure that the server knows what to expect and how to treat it properly. Usually you should split your request in a header and a payload section or something like that.
Include in your header what you want to do (e.g save player state) and the meta information of that (e.g how many bytes payload you are sending).
After the header, send the payload.
The server must now read the header 1st (like everything until the first newline), parse the header to understand what is going on (e.g save player state, 543 bytes data) and act on it (read the data, transform it to a string, deserialize the XStream object and store it in a local database or whatever the server should do with that).
So and after all this information, please adapt your question. As you have seen you do not really have a question about XStream, but about how to send some data from client to a custom server.

In what format should I respond from django to android after getting http get?

I want to send few dictionaries from django to android through HTTP after getting query in HTTP get. How can I do this and what formatting should I use?
I currently respond using HttpResponse. Name of keys are constant.
Read about serializing objects in django.
You can choose between xml, json or yaml. It's pointless to add documentation here. Goto the link.
EDIT: Django's doc is really nice. Example shouldn't really be needed. But, still, an example from one of my projects [Line 492-507 from views.py].
def pendingOrders(request):
userprof = UserProfile.objects.get(user= request.user)
if userprof.is_student:
student_account = request.user
dish = Dishes.objects.all()
#Getting all pending orders
order_all_pending = Orders.objects.filter(student_id = student_account,delivered = False)
pending_orders = Orders.objects.filter(~Q(status = 2),delivered = False)
for order in order_all_pending:
#Hack to change QuerySet to pass as JSON
order.quantity = pending_orders.filter(id__lt = order.id,counterid= order.counterid).count() + 1
#Returning JSON response to the objects obtained in above statement
return HttpResponse(serializers.serialize('json',order_all_pending,use_natural_keys=True),mimetype='application/json')
else:
return HttpResponse("Something went wrong")
https://stackoverflow.com/a/2845612/931277 Has an example of parsing json from an HttpResponse in Android.
You should use JSON. Django even makes it easy for you.

Categories