How can I marshal Objects from a Socket without closing it? (JAXB Marshaling from Inputstream via Socket) - sockets

I have tried in many different ways to send my xml document over a socket connection between a server and a client without closing the socket after sending (keep the outputstream open, for sending another document). I have found several sites who claimed that it should work, so I tried it in all the ways they sugested, but I did not found a way which works.
(that describes the same what I would like to do: http://jaxb.java.net/guide/Designing_a_client_server_protocol_in_XML.html)
The follwing code works perfectly if I am closing the socket after sending (#code marsh.marshal(element, xsw);), but it stucks on unmarshaling on the server side, if I try to keep the socket open.
Client Side....
public void sendMessage(String message){
JAXBContext jaxbContext;
try {
jaxbContext = JAXBContext.newInstance("cdl.wizard.library");
Marshaller marsh = jaxbContext.createMarshaller();
marsh.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marsh.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, "http://www.example.org/WizardShema WizardsSchema.xsd");
ObjectFactory of = new ObjectFactory();
// the Dataset is the root element of the xml document
Dataset set = new Dataset("CONN01", "CONTR", "MCL01#localhost", "SV01#localhost:32000");
CommandSet cmdSet = new CommandSet();
Command cmd = new Command();
cmd.setFunctionName("RegisterAs");
Param p = new Param();
p.setString("RemoteClient");
cmd.addParameter(p);
cmdSet.addCommand(cmd);
set.setInstruction(cmdSet);
// creates a valid xml dataset, with startDocument, startElement...
JAXBElement<Dataset> element = of.createData(set);
XMLStreamWriter xsw = XMLOutputFactory.newInstance().createXMLStreamWriter(mOOS);
marsh.marshal(element, xsw);
xsw.flush();
} catch (JAXBException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (XMLStreamException e) {
e.printStackTrace();
} catch (FactoryConfigurationError e) {
e.printStackTrace();
}
SERVER Side....
private void handleMessage() {
JAXBContext jaxbContext;
try {
jaxbContext = JAXBContext.newInstance("cdl.wizard.library") ;
Unmarshaller um = jaxbContext.createUnmarshaller();
XMLInputFactory xmlif = XMLInputFactory.newInstance();
// XMLEventReader xmlr = xmlif.createXMLEventReader(mOIS);
XMLStreamReader xmlr = xmlif.createXMLStreamReader(mOIS, "UTF8");
// move to the root element and check its name.
xmlr.nextTag();
System.out.println("TagName:" + xmlr.getLocalName());
xmlr.require(START_ELEMENT, null, "Data");
JAXBElement<Dataset> obj = um.unmarshal(xmlr, Dataset.class);
Dataset set = obj.getValue();
System.out.println("ID:"+ set.getID());
} catch (JAXBException e) {
e.printStackTrace();
} catch (XMLStreamException e) {
e.printStackTrace();
} catch (FactoryConfigurationError e) {
e.printStackTrace();
}
}

Related

Android Webview set proxy programmatically Kitkat

How can we set proxy in Android webview programmatically on latest Kitkat release?
This SO link WebView android proxy talks about version upto SDK version 18. But those solution no more works with Kitkat as underlying webkit implementation is changed and it uses chromium now.
Here is my solution:
public static void setKitKatWebViewProxy(Context appContext, String host, int port) {
System.setProperty("http.proxyHost", host);
System.setProperty("http.proxyPort", port + "");
System.setProperty("https.proxyHost", host);
System.setProperty("https.proxyPort", port + "");
try {
Class applictionCls = Class.forName("android.app.Application");
Field loadedApkField = applictionCls.getDeclaredField("mLoadedApk");
loadedApkField.setAccessible(true);
Object loadedApk = loadedApkField.get(appContext);
Class loadedApkCls = Class.forName("android.app.LoadedApk");
Field receiversField = loadedApkCls.getDeclaredField("mReceivers");
receiversField.setAccessible(true);
ArrayMap receivers = (ArrayMap) receiversField.get(loadedApk);
for (Object receiverMap : receivers.values()) {
for (Object rec : ((ArrayMap) receiverMap).keySet()) {
Class clazz = rec.getClass();
if (clazz.getName().contains("ProxyChangeListener")) {
Method onReceiveMethod = clazz.getDeclaredMethod("onReceive", Context.class, Intent.class);
Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION);
/*********** optional, may be need in future *************/
final String CLASS_NAME = "android.net.ProxyProperties";
Class cls = Class.forName(CLASS_NAME);
Constructor constructor = cls.getConstructor(String.class, Integer.TYPE, String.class);
constructor.setAccessible(true);
Object proxyProperties = constructor.newInstance(host, port, null);
intent.putExtra("proxy", (Parcelable) proxyProperties);
/*********** optional, may be need in future *************/
onReceiveMethod.invoke(rec, appContext, intent);
}
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
I hope it can help you.
Note: The Context parameter should be an Application context as the parameter name showed, you could use your own implemented Application instance which extend Application.
I've made some changes to #xjy2061's answer.
Changes are:
getDeclaredField to getField --> You use this if you declared your own application class. Else it won't find it.
Also, remember to change "com.your.application" to your own application's class canonical name.
private static boolean setKitKatWebViewProxy(WebView webView, String host, int port) {
Context appContext = webView.getContext().getApplicationContext();
System.setProperty("http.proxyHost", host);
System.setProperty("http.proxyPort", port + "");
System.setProperty("https.proxyHost", host);
System.setProperty("https.proxyPort", port + "");
try {
Class applictionCls = Class.forName("acr.browser.barebones.Jerky");
Field loadedApkField = applictionCls.getField("mLoadedApk");
loadedApkField.setAccessible(true);
Object loadedApk = loadedApkField.get(appContext);
Class loadedApkCls = Class.forName("android.app.LoadedApk");
Field receiversField = loadedApkCls.getDeclaredField("mReceivers");
receiversField.setAccessible(true);
ArrayMap receivers = (ArrayMap) receiversField.get(loadedApk);
for (Object receiverMap : receivers.values()) {
for (Object rec : ((ArrayMap) receiverMap).keySet()) {
Class clazz = rec.getClass();
if (clazz.getName().contains("ProxyChangeListener")) {
Method onReceiveMethod = clazz.getDeclaredMethod("onReceive", Context.class, Intent.class);
Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION);
/*********** optional, may be need in future *************/
final String CLASS_NAME = "android.net.ProxyProperties";
Class cls = Class.forName(CLASS_NAME);
Constructor constructor = cls.getConstructor(String.class, Integer.TYPE, String.class);
constructor.setAccessible(true);
Object proxyProperties = constructor.newInstance(host, port, null);
intent.putExtra("proxy", (Parcelable) proxyProperties);
/*********** optional, may be need in future *************/
onReceiveMethod.invoke(rec, appContext, intent);
}
}
}
return true;
} catch (ClassNotFoundException e) {
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
String exceptionAsString = sw.toString();
Log.v(LOG_TAG, e.getMessage());
Log.v(LOG_TAG, exceptionAsString);
} catch (NoSuchFieldException e) {
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
String exceptionAsString = sw.toString();
Log.v(LOG_TAG, e.getMessage());
Log.v(LOG_TAG, exceptionAsString);
} catch (IllegalAccessException e) {
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
String exceptionAsString = sw.toString();
Log.v(LOG_TAG, e.getMessage());
Log.v(LOG_TAG, exceptionAsString);
} catch (IllegalArgumentException e) {
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
String exceptionAsString = sw.toString();
Log.v(LOG_TAG, e.getMessage());
Log.v(LOG_TAG, exceptionAsString);
} catch (NoSuchMethodException e) {
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
String exceptionAsString = sw.toString();
Log.v(LOG_TAG, e.getMessage());
Log.v(LOG_TAG, exceptionAsString);
} catch (InvocationTargetException e) {
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
String exceptionAsString = sw.toString();
Log.v(LOG_TAG, e.getMessage());
Log.v(LOG_TAG, exceptionAsString);
} catch (InstantiationException e) {
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
String exceptionAsString = sw.toString();
Log.v(LOG_TAG, e.getMessage());
Log.v(LOG_TAG, exceptionAsString);
}
return false;
}
I am creating a cordova android application, and couldn't figure out why ajax requests to internal hosts on my company's network were failing on KitKat. All native web requests succeeded, and all ajax requests on android versions below 4.4 succeeded aswell. The ajax requests only failed when on the internal company wifi which was even more perplexing.
Turns out KitKat uses a new chrome webview which is different from the standard webviews used in previous android versions. There is a bug in the version of chromium that kitkat uses where it doesn't respect the proxy exclusion list. Our company wifi sets a proxy server, and and excludes all internal hosts. The ajax requests were ultimately failing because authentication to the proxy was failing. Since these requests are to internal hosts, it should have never been going through the proxy to begin with. I was able to adapt xjy2061's answer to fit my usecase.
Hopefully this helps someone in the future and saves them a few days of head banging.
//Set KitKat proxy w/ proxy exclusion.
#TargetApi(Build.VERSION_CODES.KITKAT)
public static void setKitKatWebViewProxy(Context appContext, String host, int port, String exclusionList) {
Properties properties = System.getProperties();
properties.setProperty("http.proxyHost", host);
properties.setProperty("http.proxyPort", port + "");
properties.setProperty("https.proxyHost", host);
properties.setProperty("https.proxyPort", port + "");
properties.setProperty("http.nonProxyHosts", exclusionList);
properties.setProperty("https.nonProxyHosts", exclusionList);
try {
Class applictionCls = Class.forName("android.app.Application");
Field loadedApkField = applictionCls.getDeclaredField("mLoadedApk");
loadedApkField.setAccessible(true);
Object loadedApk = loadedApkField.get(appContext);
Class loadedApkCls = Class.forName("android.app.LoadedApk");
Field receiversField = loadedApkCls.getDeclaredField("mReceivers");
receiversField.setAccessible(true);
ArrayMap receivers = (ArrayMap) receiversField.get(loadedApk);
for (Object receiverMap : receivers.values()) {
for (Object rec : ((ArrayMap) receiverMap).keySet()) {
Class clazz = rec.getClass();
if (clazz.getName().contains("ProxyChangeListener")) {
Method onReceiveMethod = clazz.getDeclaredMethod("onReceive", Context.class, Intent.class);
Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION);
/*********** optional, may be need in future *************/
final String CLASS_NAME = "android.net.ProxyProperties";
Class cls = Class.forName(CLASS_NAME);
Constructor constructor = cls.getConstructor(String.class, Integer.TYPE, String.class);
constructor.setAccessible(true);
Object proxyProperties = constructor.newInstance(host, port, exclusionList);
intent.putExtra("proxy", (Parcelable) proxyProperties);
/*********** optional, may be need in future *************/
onReceiveMethod.invoke(rec, appContext, intent);
}
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
You would call the method above as follows:
First import this library at the top of your file.
import android.util.ArrayMap;
Then call the method
int currentapiVersion = android.os.Build.VERSION.SDK_INT;
//check first to see if we are running KitKat
if (currentapiVersion >= Build.VERSION_CODES.KITKAT){
setKitKatWebViewProxy(context, proxy, port, exclusionList);
}
https://android.googlesource.com/platform/external/chromium/+/android-4.4_r1/net/proxy/proxy_config_service_android.cc
Has methods to set the proxy. I am still trying to figure out how to invoke this from Java code. Pointers?
https://codereview.chromium.org/26763005
Guess from this patch, you'll be able to set up a proxy again in the near future, perhaps.
Had some issues with the provided solution on some devices when loading page from onCreate right away after setting the proxy configuration. Opening the web page after some small delay solved the problem. Seems like the proxy config needs some time to get effective.

POST over SSL/HTTPS REST Api Android is responding 400 Bad Request

In my application I want to post from my android application XML data in the remote server which is using REST service. My code is below:
String url = "api.example.com";
int port = 443;
String query = "<?xml version='1.0' encoding='UTF-8'?><request><client><name>APIappDevAccount</name><password>123456</password></client><user><name>foyzulkarim</name><password>123456</password><groupId>12345</groupId></user></request>";
Socket socket = null;
try {
socket = new Socket(url,port);
} catch (UnknownHostException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
} catch (IOException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
PrintStream pw = null;
try {
pw = new PrintStream(socket.getOutputStream());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
pw.print("POST api.example.com/rest/rest/user");
pw.print("Content-Type: application/xml");
pw.print("Content-Length:" + query.length());
pw.print(query);
System.out.println("hello foysal.");
//get result
String l = null;
String text="";
try {
while ((l=br.readLine())!=null) {
System.out.println(l);
text+=l;
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
pw.close();
try {
br.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
But that server is behind SSL/HTTPS protocol so i am getting the below 400 Bad Request as response.
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"><html><head><title>400 Bad Request</title></head><body><h1>Bad Request</h1><p>Your browser sent a request that this server could not understand.<br />Reason: You're speaking plain HTTP to an SSL-enabled server port.<br />Instead use the HTTPS scheme to access this URL, please.<br /><blockquote>Hint: <b>https://api.example.com/</b></blockquote></p></body></html>
If I use SSLSocketFactory like below
SocketFactory socketFactory = SSLSocketFactory.getDefault();
Socket socket = null;
try {
socket = socketFactory.createSocket(url, port);
I got exception
javax.net.ssl.SSLException: Not trusted server certificate
java.security.cert.CertPathValidatorException: TrustAnchor for CertPath not found.
at line
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
My question is, how can i post the data over SSL from android application in my above scenario?
I guess many of us are facing this problem, so I am requesting you to give me/us some elaborated answers.Cheers.
Too many unknowns :-)
Try plain HTTP against a test server you have control over.
My hunch is it will give the same error.
You don't seem to put an empty line between the HTTP headers and body for example.
Why are you re-implementing HTTP anyway? Don't tell me there's no API or library you could use on whatever platform this is? Usually there's java.net.HttpUrlConnection, or Apache HttpClient.
Edit:
Hey, look what google brought in: http://developer.android.com/reference/android/net/http/AndroidHttpClient.html
It seems that I needed to add the TrustAnchor certificate to be able to validate the whole key chain.
I have requested about this certificate to my API Provider and they given me the web link from where I can get the certificate. [i have changed the web link for confidentiality]
https://www.example.com/library/......SSL_bundle.pem
They also told me to get try the connection via (i guess it should be executed from command prompt)
openssl s_client -connect api.example.com:443 -CAfile /root/SSL_bundle.pem
I then have to integrate the certificate into my application.
I will now try to know how can I integrate that certificate, but that discussion should be in another question.
I have done it. The code is given below.
private String executeRequest(String targetURL, final String requestMethod,
String soap_request_message_header, String soap_request_message_body) {
URL url;
HttpURLConnection connection = null;
try {
url = new URL(targetURL);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod(requestMethod);
connection.setRequestProperty("SOAPAction",
soap_request_message_header);
connection.setUseCaches(false);
connection.setDoInput(true);
connection.setDoOutput(true);
// Send request
DataOutputStream wr = new DataOutputStream(connection
.getOutputStream());
wr.writeBytes(soap_request_message_body);
wr.flush();
wr.close();
// Get Response
InputStream is;
final int responseCode = connection.getResponseCode();
Log.i("response", "code=" + responseCode);
if (responseCode <= 400) {
is = connection.getInputStream();
} else {
/* error from server */
is = connection.getErrorStream();
}
// is= connection.getInputStream();
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
String line;
StringBuffer response = new StringBuffer();
while ((line = rd.readLine()) != null) {
response.append(line);
response.append('\r');
}
rd.close();
Log.i("response", "" + response.toString());
return response.toString();
} catch (Exception e) {
Log.e("error https", "", e);
return e.getMessage();
} finally {
if (connection != null) {
connection.disconnect();
}
}
}

GWT displaying image specified from servlet

I use a servlet to access a folder outside the web container to load some graphics to web application by using GWT. I use the following snippet in servlet to test the idea:
String s = null;
File inputFile = new File("C:\\Documents and Settings\\User\\My Documents\\My Pictures\\megan-fox.jpg");
FileInputStream fin = null;
try {
fin = new FileInputStream(inputFile);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
byte c[] = new byte[(int) inputFile.length()];
try {
fin.read(c);
} catch (IOException e) {
e.printStackTrace();
}
try {
fin.close();
} catch (IOException e1) {
e1.printStackTrace();
}
String imgFolderPath = getServletContext().getRealPath("/")+"img";
File imgFolder = new File(imgFolderPath);
imgFolder.mkdir();
File newImage = new File("megan-fox.jpg");
FileOutputStream fout = null;
try {
fout = new FileOutputStream(newImage);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
try {
fout.write(c);
} catch (IOException e) {
e.printStackTrace();
}
try {
fout.close();
} catch (IOException e) {
e.printStackTrace();
}
boolean success = newImage.renameTo(new File(imgFolderPath, newImage.getName()));
The code in servlet reads the image file from the specified folder in hard disk, creates a new folder called 'img' in war folder and copies to it the jpg file. Then it returns to the client the path to the image (for now hardcoded as) '/img/megan-fox.jpg'.
The client then uses the Image class in GWT with the returned path-string to display the image, like in the following snippet:
public void onSuccess(String result) {
String myImage = result;
image = new Image(myImage);
RootPanel.get().add(image);
closeButton.setFocus(true);
}
I need to know if there is a way to achieve the same result without using the 'intermediate' step of creating a folder in the web container root (optional) and copying the file there in order to access it with Image GWT class and display it?
updated: The original servlet class.
public class GreetingServiceImpl extends RemoteServiceServlet implements
GreetingService {
// This method is called by the servlet container to process a GET request.
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
// Get the absolute path of the image
ServletContext sc = getServletContext();
// i want to load the image in the specified folder (outside the web container)
String filename = sc.getRealPath("C:\\Documents and Settings\\User\\My Documents\\My Pictures\\megan-fox.jpg");
// Get the MIME type of the image
String mimeType = sc.getMimeType(filename);
if (mimeType == null) {
sc.log("Could not get MIME type of "+filename);
resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
return;
}
// Set content type
resp.setContentType(mimeType);
// Set content size
File file = new File(filename);
resp.setContentLength((int)file.length());
// Open the file and output streams
FileInputStream in = new FileInputStream(file);
OutputStream out = resp.getOutputStream();
// Copy the contents of the file to the output stream
byte[] buf = new byte[1024];
int count = 0;
while ((count = in.read(buf)) >= 0) {
out.write(buf, 0, count);
}
in.close();
out.close();
}
// This is the method that is called from the client using GWT-RPC
public String greetServer(String input) throws IllegalArgumentException {
HttpServletRequest req = this.getThreadLocalRequest();
HttpServletResponse res = this.getThreadLocalResponse();
try {
doGet(req, res);
} catch (IOException e) {
e.printStackTrace();
}
// actually i dont know what that means but i thought i would have to returned something like the image's url?
return res.encodeURL("/img/image0.png");
}
}
I logically misused the method that was proposed to solve my problem. What is the correct way?
Sure, just have your servlet serve the image directly:
Set the Content-Type header to image/jpeg.
Write out image file contents to servlet response writer.
Here is an example.

linking my applet to a server dirctory to recieve or save a file from there?

I' m looking for a code to save the files created in a applet normally text files i want to save them on a server directory how can i do so.
Here is an example of how to send a String. In fact any Object can be sent this method so long as it's serializable and the same version of the Object exists on both the applet and the servlet.
To send from the applet
public void sendSomeString(String someString) {
ObjectOutputStream request = null;
try {
URL servletURL = new URL(getCodeBase().getProtocol(),
getCodeBase().getHost(),
getCodeBase().getPort(),
"/servletName");
// open the connection
URLConnection con = servletURL.openConnection();
con.setDoOutput(true);
con.setUseCaches(false);
con.setRequestProperty("Content-Type", "application/octet-stream");
// send the data
request =
new ObjectOutputStream(
new BufferedOutputStream(con.getOutputStream()));
request.writeObject(someString);
request.flush();
// performs the connection
new ObjectInputStream(new BufferedInputStream(con.getInputStream()));
} catch (Exception e) {
System.err.println("" + e);
} finally {
if (request != null) {
try {
request.close();
} catch (Exception e) {
System.err.println("" + e);
};
}
}
}
To retrieve on the server side
#Override
public void doPost(HttpServletRequest request, HttpServletResponse response) {
try {
// get the input stream
ObjectInputStream inputStream = new ObjectInputStream(
new BufferedInputStream(request.getInputStream()));
String someString = (String)inputStream.readObject();
ObjectOutputStream oos = new ObjectOutputStream(
new BufferedOutputStream(response.getOutputStream()));
oos.flush();
// handle someString....
} catch (SocketException e) {
// ignored, occurs when connection is terminated
} catch (IOException e) {
// ignored, occurs when connection is terminated
} catch (Exception e) {
log.error("Exception", e);
}
}
No one is going to hand you this on a plate. You have to write code in your applet to make a socket connection back to your server and send the data. One way to approach this is to push the data via HTTP, and use a library such as commons-httpclient. That requires your server to handle the appropriate HTTP verb.
There are many other options, and the right one will depend on the fine details of the problem you are trying to solve.

webservice SOAP message Monitor or logging

Could some one tell me how to capture SOAP messages passed between the client and the server webservice applications.
I tried using both tools.
pocket soap
http://www.pocketsoap.com/pocketsoap/
Fiddler
http://www.fiddlertool.com/fiddler/
I may miss some settings, it is not working for me.
help will be more appreciated.
Try tcpmon.
soapUI integrates with tcpmon, and may provide a nicer interface for you.
See also; You can try the MS Visual Roundtrip Analyzer analyzer as well.
if you're interested, you can write a handler in Java which extends the GenericSOAPHandler class, and print the output to wherever you like. In this (simple) case, the server log:
#SuppressWarnings("rawtypes")
public class MyHandler extends GenericSOAPHandler {
private void print(InputStream input, OutputStream out) throws Exception {
try {
DocumentBuilder parser;
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
parser = factory.newDocumentBuilder();
Document document = parser.parse(input);
Transformer serializer = TransformerFactory.newInstance().newTransformer();
serializer.setOutputProperty(OutputKeys.INDENT, "yes");
serializer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
serializer.transform(new DOMSource(document), new StreamResult(out));
} catch (TransformerException e) {
// A fatal error occurred
throw new Exception(e);
}
}
#Override
protected boolean handleInbound(MessageContext msgContext) {
SOAPMessageContext soapMessageCtx = (SOAPMessageContext) msgContext;
SOAPMessage soapMessage = soapMessageCtx.getMessage();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
try {
soapMessage.writeTo(outputStream);
byte[] array = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(array);
System.out.println("SOAP request message:\n");
print(inputStream, System.out);
} catch (SOAPException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return true;
}
#Override
protected boolean handleOutbound(MessageContext msgContext) {
SOAPMessageContext soapMessageCtx = (SOAPMessageContext) msgContext;
SOAPMessage soapMessage = soapMessageCtx.getMessage();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
try {
soapMessage.writeTo(outputStream);
byte[] array = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(array);
System.out.println("SOAP response message:\n");
print(inputStream, System.out);
} catch (SOAPException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return true;
}
}
You also need to make sure your handler is included in the jaxws-handlers-server.xml of your server implementation:
<handler-chains xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee javaee_web_services_1_2.xsd">
<handler-chain>
<protocol-bindings>##SOAP11_HTTP</protocol-bindings>
<handler>
<handler-name>DebugHandler</handler-name>
<handler-class>handlers.MyHandler</handler-class>
</handler>
</handler-chain>
</handler-chains>
Here my code in C++ for retrieve xml message using Soap Toolkit 3.0 before sending.
.
.
.
Serializer->EndEnvelope();
/* ___________________ */
char * bufferxml = NULL;
_variant_t punt = _variant_t((IUnknown*)Serializer);
punt.lVal += 48;
_variant_t punt1 = *punt.ppunkVal;
punt1.lVal += 32;
_variant_t punt2 = *punt1.ppunkVal;
punt2.lVal += 4;
memcpy(&bufferxml, (char *) *punt2.ppunkVal, sizeof(char *));
punt2.lVal += 4;
int lengxml = *(punt2.pintVal);
bufferxml[lengxml] = '\0';
/* ___________________ */
// Send the message to the web service
Connector->EndMessage();
.
.
.
punt.Detach();
punt1.Detach();
punt2.Detach();
punt.Clear();
punt1.Clear();
punt2.Clear();
Serializer.Release();
.
.
.
I hope really help you, it´s my design and it had worked for me.
There is also TCP/IP Monitor which comes bundled with WTP plugin for eclipse which allows you to set up a monitor on a port to look into the SOAP requests.