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.
Related
I have a Java application that gets information on a general purpose channel.
I cannot listen on another port, and the application does not have(or implements) a webserver.
I want to activate some of the application's functionalities via REST API.
I already have the requested URI and parameters(of a single client request), but they are not in an HTTPRequest class.
How can I directly call the Spring REST API, using the data I have?
To illustrate what I want to do:
In myREST.java:
class myREST {
#RequestMapping(value = "/foos", method = RequestMethod.GET)
#ResponseBody
public List<Foo> getAllFoos {
return foos;
}
}
and in another file:
JSONObject restAPICaller(String uri, JSONObject params) {
JSONObject response = springRestAPI.call(uri, "GET", params);
return response;
}
where for instance, my uri is /foos/ , and params is {} (will have content for other examples)
How can I directly call the Spring REST API, using the data I have?
You cannot use an API via an HTTP client without an HTTP server.
I guess you can either:
Embed a server in your app and have it listen on some network port (you can bind to 127.0.0.1, so that the service is not accessible from other machines).
Directly call into the REST API classes (eg: new myREST(). getAllFoos())
Call into the business logic layer your API classes call into (iff you properly structured your code there)
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.
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...
I am trying to implement a web service that proxies another service that I want to hide from external users of the API. Basically I want to play the middle man to have ability to add functionality to the hidden api which is solr.
I have to following code:
#POST
#Path("/update/{collection}")
public Response update(#PathParam("collection") String collection,
#Context Request request) {
//extract URL params
//update URL to target internal web service
//put body from incoming request to outgoing request
//send request and relay response back to original requestor
}
I know that I need to rewrite the URL to point to the internally available service adding the parameters coming from either the URL or the body.
This is where I am confused how can I access the original request body and pass it to the internal web service without having to unmarshall the content? Request object does not seem to give me the methods to performs those actions.
I am looking for Objects I should be using with potential methods that would help me. I would also like to get some documentation if someone knows any I have not really found anything targeting similar or portable behaviour.
Per section 4.2.4 of the JSR-311 spec, all JAX-RS implementations must provide access to the request body as byte[], String, or InputStream.
You can use UriInfo to get information on the query parameters. It would look something like this:
#POST
#Path("/update/{collection}")
public Response update(#PathParam("collection") String collection, #Context UriInfo info, InputStream inputStream)
{
String fullPath = info.getAbsolutePath().toASCIIString();
System.out.println("full request path: " + fullPath);
// query params are also available from a map. query params can be repeated,
// so the Map values are actually Lists. getFirst is a convenience method
// to get the value of the first occurrence of a given query param
String foo = info.getQueryParameters().getFirst("bar");
// do the rewrite...
String newURL = SomeOtherClass.rewrite(fullPath);
// the InputStream will have the body of the request. use your favorite
// HTTP client to make the request to Solr.
String solrResponse = SomeHttpLibrary.post(newURL, inputStream);
// send the response back to the client
return Response.ok(solrResponse).build();
One other thought. It looks like you're simply rewriting the requests and passing through to Solr. There are a few others ways that you could do this.
If you happen to have a web server in front of your Java app server or Servlet container, you could potentially accomplish your task without writing any Java code. Unless the rewrite conditions were extremely complex, my personal preference would be to try doing this with Apache mod_proxy and mod_rewrite.
There are also libraries for Java available that will rewrite URLs after they hit the app server but before they reach your code. For instance, https://code.google.com/p/urlrewritefilter/. With something like that, you'd only need to write a very simple method that invoked Solr because the URL would be rewritten before it hits your REST resource. For the record, I haven't actually tried using that particular library with Jersey.
1/ for the question of the gateway taht will hide the database or index, I would rather use and endpoint that is configured with #Path({regex}) (instead of rebuilding a regexp analyser in your endpoint) .
Use this regex directly in the #path, this is a good practice.
Please take a look at another post that is close to this : #Path and regular expression (Jersey/REST)
for exemple you can have regexp like this one :
#Path("/user/{name : [a-zA-Z][a-zA-Z_0-9]}")
2/ Second point in order to process all the request from one endpoint, you will need to have a dynamic parameter. I would use a MultivaluedMap that gives you the possibility to add params to the request without modifying your endpoint :
#POST
#Path("/search")
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
#Produces({"application/json"})
public Response search( MultivaluedMap<String, String> params ) {
// perform search operations
return search( params);
}
3/ My 3rd advice is Reuse : make economy and economy make fewer bugs.
it's such a pitty to rewrite a rest api in order to perform solr search. You can hide the params and the endpoint, but could be great to keep the solr uri Rest formatting of the params in order to reuse all the search logic of solr directly in your api. This will make you perform a great economy in code even if you hide your solr instance behind you REST GATEWAY SERVER.
in this case you can imagine :
1. receive a query in search gateway endpoint
2. Transform the query to add your params, controls...
3. execute the REST query on solr (behind your gateway).
I have a Java WebService setup which consumes an xml file and want to be able to produce either xml or json based on what the client requests. I know that this is possible through reading up on Jersey REST methods but it does not show how to extract this information. I have also looked on google all over but can't seem to find any examples of this.
http://wikis.sun.com/display/Jersey/Overview+of+JAX-RS+1.0+Features is the site that I was initially referencing which shows that it is possible, I was just wondering if anyone would be able to help me find out how to actually distinguish the client's request. Is it in the html header? body? And if so what is the proper way to extract it?
This is what my method currently looks like, I do not have any issues with connection, just finding out what the client requests as a return type.
#POST
#Path("getStatisticData")
#Produces ({"application/xml","application/json"})
#Consumes ("application/xml")
public String getStatisticData(#FormParam("xmlCoords") String xmlFile) throws Exception{
Thanks in advance.
You can extract it using the #HeaderParam annotation:
...
public String getStatisticData(#HeaderParam("Accept") String accept,
#FormParam("xmlCoords") String xmlFile) throws Exception {
...
}
The Accept header in the request is used for the client to indicate to the server what methods it supports.
If the client can set HTTP headers, the proper way to do it is to use the Accept header:
http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
IF this is not possible, the type requested could be passed in as an argument.
Alternatively, expose two different web services: one that returns XML, one that returns JSON. Each web service would call the same code but with a parameter specifying which format to use.