I have to send an XML-file from one java Application to another.
Currently, it works like this:
- Export to local XML-file from application 1
- Import local XML-file in application 2
Now I have to do this via web service(s). Is it possible to create a JAX-WS web service in application 1 that redirects to application 2 with the data needed?
I can send the data (object) as a serialized object, instead of a XML-file. But is this possible? And if so, how?
Both applications are written in Eclipse-Scout.
Thanks in advance.
webservice is simple and usefull if your two apps run on different machines.
Sending server:
use a library for http (post or get)
1 only keep your file. just use an HTTP / POST. works for text an binary
2 more simple: if your datas are little text, you can use HTTP / GET (beware of special characters: you can encode them).
3 if you can put all your datas in one structure (object), just serialize it, put the result in a String, and send it.
Receiving server:
if you use tomcat, extend HttpServlet, and get by doPost or doGet
Or you can use another light http server
Or soap library (no really need).
DOPOST/DOGET
Sending server:
HttpURLConnection conn= (HttpURLConnection) url.openConnection(); // etc.
Receiving server:
public class MyServlet extends HttpServlet {
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String one_parameter = request.getParameter("name_of_parameter");
See these links for more explanation:
Java - sending HTTP parameters via POST method easily
doGet and doPost in Servlets
(A bit long for a comment)
You may want to stay away from bloated things like JAX-WS and just use a standard Servlet and JAXB or XStream for de-/serialisation.
Also, do not ever use Java (binary) deserialisation or default XStream on unauthenticated inputs/transport (e.g. HTTP or untrusted clients even with HTTPS). It always leads to remote code execution exploits that cannot be migitated without redeveloping your webservice interface. Most recent instance...
Related
We have our Web API written in using RESTEasy. We would like to provide support for Batch requests processing the way Google Batch request processing works.
Following is the approach which are using currently,
We have a filter which accepts incoming multipart request. This filter then creates multiple mock requests and response objects and then calls chain.doFilter using these mock requests.
public class BatchRequestProcessingFilter extends GenericFilterBean {
#Override
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)req;
MockHttpServletRequest[] mockRequests = BatchRequestProcessorUtils.parseRequest(request);
MockHttpServletResponse[] mockResponses = new MockHttpServletResponse[mockRequests.length];
for(int i=0 ; i <= mockRequests.length ; i++ ) {
chain.doFilter(mockRequests[i], mockResponses[i], chain);
}
BatchRequestProcessingUtils.populateResponseFromMockResponses(res, mockResponses);
}
}
MockHttpServletResponse class returns a dummy OutputStream which wraps ByteArrayOutputStream.
BatchRequestProcessorUtils parses the multipart request and returns the mock request which wraps actual request but returns the header specified in split body of the actual request body.
I could not find any existing library which supports batch request processing. So my question is that, is this the correct approach to support batch request or is there any standard way which should be used?
Note that we are using Tomcat 8.
Sachin Gorade. I have not heard about such libraries, but I think your approach is reasonable. If I had to solve that problem, I would think like this:
In our HTTP servlets we can process requests only separately, and it is the reason why we should wrap all requests, that we want to send, into another single request at client side.
As on our server side we have only one request, then we should unwrap all requests we have put into it. And, because we dont know how to process each request in our batch mechanizm - we shold send it through all filters/servlets. Also it is a reason to put our batch filter at the first position in the order.
Eventually, when all requests has been processed, we should send a response back to the client. And again, to do that we should wrap all responses into a single one.
At the client side we should unwrap responses and send each of that to some objects, that can process it.
In my oponion there should be two mechanizms:
Batch sender for client side, that is responsible for collecting and wrapping requests, unwrapping responses and sending them to theirs processors(methods that process regular responses).
Batch processor for server side, that is responsible for unwrapping requests, and collecting and wrapping responses.
Of course, that two parts may be coupled (i.g. to have shared "Wrapper" module), because objects we must be wrapped and unwrapped in the same way.
Also, if I worked on it, I would try to develop the client side mechanizm like a decorator upon a class that I use to send regular requests. In that case, I would be able to substitute regular/batch mode anytime I need to do it.
Hope my opinion is helpful for you.
How do I change HTTP method in javax,servlet.RequestDispatcher?
I have some old service APIs that support GET and POST, The new version supports DELETE method for removing a record which used to happen through POST earlier.
We are decommissioning old version APIs by setting RequestDispatcher.forward() for old end points (stop gap arrangement until clients change). everything was cool except this POST to DELETE mapping.
Any solution there for this problem without adding POST end point for delete operation in new API?>
Although I agree using the next layer after your servlets would be a better choice, this is interesting. It use to be common to wrap an incoming request to add request based functionality (IE: auth state, etc). The HttpServletRequestWrapper was used to accomplish this. You could do the following if you just need to change the method:
class PostDeleteAdapter extends HttpServletRequestWrapper {
public String getMethod(){ return "POST"; }
}
You may also change other aspects of the incoming request if you need to further adapt the request. This may play well with your servlet containers RequestDispatcher, however it's dependent upon the container entirely.
I think you can't do it using servlet API. You can do what you want creating a new request, processing it's response and sending it back through the original response (in the servlet).
Some http clientes might help you. See Apache HTTP client:
http://hc.apache.org/httpclient-3.x/methods/delete.html)
I have two web application, webAppMaster and webAppSlave, deployed in same tomcat server. Now in webAppMaster application, there is a java class, RequestHandler whose processRequest method takes a customObject1 as parameter and returns customObject2. Now, from RequestCreator class of webAppSlave application, I want to invoke processRequest method of RequestHandler class of webAppMaster application. How this should be done ?
Thanks in advance.
You need to talk between applications as if you were talking between two distant applications. It does not matter that they are on the same server they simply must communicate using some protocol.
What you want to do is actually RMI (remote method invokation) - http://docs.oracle.com/javase/tutorial/rmi/
Instead of using rmi you can use some more lightweight way of communication. You can communicate via Rest for example. In this case create servlet in webAppMaster application which takes as parameters your customObject1 serialized to JSON (either as URL request params or use POST method). Than this servlet will do the translation of JSON string to customObject1 and call processRequest. Later after processRequest() returns customObject2 translate it to JSON and send back to client. On client side read the json and deserialize JSON back to customObject2 in webappSlave.
public class MasterServlet extends javax.servlet.http.HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
CustomObject1 customObject1 = buildCustomObject1BasingOnRequestParams(HttpServletRequest request); // read the request params and build your object either from json or whatever format webappSlave used to send
CustomObject2 customObject2 = RequestHandler.processRequest(customObject1);
String json = transformTOJson(customObject2); // there are many libaries which does this
response.getWriter().print(json);
}
}
Your slave app would do the other way around. First serialize customObject1 to JSON, and later deserialize received JSON to customObjec2.
As a third option you can use HTTP tunneling to send objects between applications (reffer for example to this post: Serializing over HTTP correct way to convert object.) as an example.
Is there any known way to send a new SOAP request from one servlet to another within a single WebContainer without consuming an additional web container thread?
So far I have tried using RequestDispatcher.include(request, response) with a customised request and response so I can provide my own input and intercept the callee's output.
With this, I am able to intercept the output without issue (using a custom HttpServletResponse class that writes to a buffer), but I have been unable to send customised input with this method. I am using an extension of HttpServletRequestWrapper to provide my own input to the third party application (instead of the original request to my application), however it seems like either WebSphere or Axis are discarding my wrapper and I therefore get a SOAP fault instead of a valid response.
For clarity, I don't need to forward the original request to the callee (which is a JSONP GET request), I need to fabricate a new SOAP request within my application and send that to the callee instead.
Is there a variation of this method I should try? Is there a completely different way to send a request within a single web container?
Many thanks to those who respond.
For context, I am writing a JSON/REST web service to be run on WebSphere Application Server, which in turn calls a third party product via SOAP on Axis 2. Unfortunately this third party product is only available via a SOAP HTTP interface, despite itself being a Java servlet running inside the same WebSphere web container.
Previously I have been calling this application using an HTTP proxy generated with the SOAP proxy generator based on third party product's WSDL. This works fine however it means that one call to my service in turn consumes two web container threads which is a severe vulnerability. Once the web container thread pool is full, it stays full since the requests to my servlet are holding threads until the third party application responds, which it is not able to do because no threads are available to process the HTTP request my servlet made.
Update:
I have done some further testing and been able to do this type of forwarding to my REST service successfully. I am able to query my REST/JSON service with a synthetic ServletRequest and ServletResponse, therefore allowing me to achieve my original purpose if the product I was calling did not use an Axis SOAP interface.
It appears that Axis is looking in a different place for the SOAPAction header than I expected, as I always get a "no SOAPAction header found!" fault message back despite me adding a SOAPACtion header to my synthetic request (I have verified that the SOAPAction header is in fact added).
It turns out that the reason I could not get the service to work with Axis due a "missing" SOAPAction header has nothing to do with WebSphere or Axis at all. It was a ConcurrentHasMap that somehow was comparing two equivalent strings and saying they were different, so the SOAPAction header was never returned when Axis looked for it. To work around this, I simply tested for queries on 'SOAPAction' and hardcoded the response.
So, for future reference here is the general setup I used.
Create a class implementing HttpServletRequest that wraps another HttpServletRequest to be provided in the constructor. In this class the getHeader method was overridden to catch requests for the SOAPAction header, other header requests may be forwarded to the original request (Axis doesn't seem to look for anything other than the SOAPAction header). I also over-rode the getInputStream method to return my own ServletInputStream implementation that simply reads from a byte buffer using a fixed text encoding, and the getContentLength method to return a length consistent with my data.
Create a class implementing HttpServletResponse, which only correctly implements the getWriter and getOutputStream methods. The getOutputStream method return a custom ServletOutputStream implementation that records its output to a byte buffer. The getWriter method returned a special PrintWriter that wrote to the same ServletOutputStream returned by getOutputStream, except this writer always needed to flush after writing - I am not sure why this had to be case.
Before dispatching the request using RequestDispatcher.include(request, response), I wrapped my synthetic HttpServletRequest in a HttpServletRequestWrapper, which oddly seemed to help. I then used RequestDispatcher.include(request, response) in the usual fashion, and read the SOAP service's output from my custom ServletOutputStream's byte buffer to process as it in the same as if I had issued an HTTP request.
I've a third-party servlet inside a JAR that I cannot change. I've extended that servlet and been using it normally as a servlet should be used, the client side makes an HTTP request that invokes my servlet.
But now the client wants an automatic service, that is, I will need to do some requests to that third party servlet from the same webapp where the servlet is.
I looked at the the third party servlet code but I didn't found a place to bypass the servlet because the HttpServletRequest and HttpServletResponse objects are passed from method to method... Basically it seems that I would need to re-implement all the third party code.
Solutions I found but do not satisfy me:
Call servlet from URL with HttpURLConnection: My common sense says that calling the third party servlet from a url is not the best way to
go, besides the overhead added, I don't want to expose the third party
servlet. Calling my servlet from a url also brings problems with
sessions and other things.
Call the doGet directly: This seems to be out of the question because there is no implementation for the HttpServletRequest and
HttpServletResponse.
Use jMock or something like that: Didn't explore this solution yet, but it seams wrong to use a test-driven library in the real
environment.
Anyone has an idea how to interact with that third party servlet?
EDIT:
Since my English is not very good and I'm finding difficult to explain myself here goes a schematic to try to explain better
EDIT2: After a meeting the third party maker they offer to isolate the methods I need to avoid calling the servlet. If you don't have the same luck I did check out both gigadot and BalusC answers.
If I understand your question correctly, you have implemented or have a third party servlet that generate the report for you.
Now what you want to do is to periodically generate the report and store in session so that when user want to get the report they can retrieve it using another servlet.
If this is the case then you want the task to be running periodically on your server. You will need some sort of task scheduler to run on your server and what the task does is just make a http request to your servlet (this can be http GET or POST).
Calling my servlet from a url also brings problems with sessions and other things.
If that's the sole problem, then just use the CookieManager to maintain the cookies (and thus also the session) in subsequent URLConnection calls.
// First set the default cookie manager.
CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ALL));
// All the following subsequent URLConnections will use the same cookie manager.
URLConnection connection = new URL(url).openConnection();
// ...
connection = new URL(url).openConnection();
// ...
connection = new URL(url).openConnection();
// ...
See also:
Using java.net.URLConnection to fire and handle HTTP requests
You could try to separate out your servlet logic into several phases. The entry point that takes the request/result, the action that processes parameters sent and generates the output.
public void doGet(HttpServletRequest req, HttpServletResponse rsp){
relay(rsp,act(req.getParameter("a"));
}
public static String act(String a){
return "You provided: " + a;
}
public static void relay(HttpServletResponse rsp, String content){
rsp.setResponseCode(200);
rsp.getOutputStream().write(content.getBytes());
}
This lets you call act(whatever) to do what you want, and then do what you want with the response. If returning a string is not enough, you could make any return type you want, probably something that could contain a list of headers, response code, and content template.