How to manage requests without get parameters - java

I am currently using front controller pattern in a Java servlet and and redirecting requests to an appropriate handler via a "action" GET parameter. So, every link or process in the application will route to the front controller with an appropriate ?action=x query string and then the front controller uses the output from request.getParameter("action") to load and execute the appropriate handler.
How can I do this without having query strings in all of my URLs on the web application?

Here is the general approach used by most of the HTTP services framework.
You can use two things to decide about the handlers mapping:
The reference URL of entity i.e. URL part appended to the base URL of your application
The Http method, if you want to have different handlers for different HTTP operations
For example, you have this URL
http://mydomain.com/myapplication/myentity
Here the base URL part is: http://mydomain.com/myapplication/
Entity reference URL part is: myentity
Also the operation can be mapped to the HTTP method : GET(get), POST(create), DELETE(remove), PUT(update)
So you should have mapping of refURL myentity to some handler like MyEntityHandler class alongwith the operartion(optional). Pass the input request and response object for necessary information to the handler class.

Related

Can I create a response object in java without creating a servlet?

Can I create a response object in java without creating a Servlet? I have a regular java class right now called Menu. It contains not only my menus for my application but it also contains my CRUD functionality that is tied to the database. Which works fine on the console. What I want to do now is to display the result set on a webpage. I want to use AJAX (no frameworks like jQuery etc.) to capture the information from the result set. In the Menu class I am going to convert the extracted information into a Json string with Jackson databinding (object mapper). I want to use a PrintWriter to send this information back to AJAX. I am assuming I need a response object. Do I have to re-write my Menu class as a Servlet or is there another way to accomplish this?
For querying data from server you need to have a resource which has
http url
can accept a form of request as input
can give response based on business logic in menu crud class.
For this querying as you said you can do with ajax call to this servlet with specified url pattern from your frontend webpage.
In short servlet will be essential. It can handle all http method types like get post and so on.
So you can map your crud methods to your servlet methods
eg :
doGet - querying items.
doPost- creation of item.
doDelete- delete an item.
and so on.
further you will call your crud methods from these servlet do* methods.
for example refer: https://www.geeksforgeeks.org/servlet-crud-operation-with-example/
Hope this helps.

Any simple way to test a #RequestBody method?

If I have a #Controller method whose parameter is a #RequestBody param, I usually have to write some jQuery script or something similar to perform an AJAX request with JSON object in order to call that method. If I tried calling that method via a web browser directly, it returns with a Error 415 Unsupported Media Type.
Is there any alternative to just quickly call such method using browser without having to write some jQuery code? Like perhaps a way to write the JSON object in the URL/address bar?
code:
#RequestMapping("testCall")
#ResponseBody
public List<TestObject> getTestCall (#RequestBody TestParams testParams) {
return stuff;
}
public class TestParams {
private Integer testNumber;
//getter/setter for testNumber
}
I thought maybe I could just do:
http://localhost/testCall?testNumber=1
maybe Spring would auto populate a new TestParams instance with that property set to 1 but that didnt work...
maybe I need to do something extra for that?
The whole point of a #RequestBody annotated parameters is for the Spring MVC stack to use the HTTP request body to produce an argument that will be bound to the parameter. As such, you need to provide a request body. Sending a request body is very atypical for a GET request. As such, browsers don't typically support it, at least not when simply entering an address in the address bar and submitting the request.
You'll need to use a different HTTP client, like jQuery. I typically have a small Java project in Eclipse that's setup with an Apache HTTP components client which can send HTTP requests to whatever server. It takes a few seconds/minutes to setup the correct request body and run.
I have spent the last year building a REST API, and by far the best way to exercise that API manually is using the Chrome Extension, Postman. I cannot recommend this tool enough.
https://chrome.google.com/webstore/detail/postman-rest-client/fdmmgilgnpjigdojojpjoooidkmcomcm?hl=en
To test your simple example you'll need to invoke a POST (I assume that as you have a request body, but your controller method doesn't define a HTTP Verb) using POSTMAN to your Url (like the following example):
POST /contextRoot/testCall
{
"testNumber": 1
}
If you want to test your API automatically (which I recommend), you can use the excellent Spring Mvc Test project. This allows your to call your API via a rest-like DSL and assert that the response is in the shape you want. More details can be found here:
http://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/testing.html#spring-mvc-test-framework
you can add request params to the getTestCall method:
#RequestParam(value = "testNumber", required = false, defaultValue = "") String testNumber
There is a chrome app called Advanced REST client. You can pass the data in form of json to your controller using this chrome app. For eg. json data is
id:1,
name:"xyz"
whereas the controller can have #RequestBody Person form.
The Person class would be a POJO having id and name as instance variables. The Spring would automatically map the json data to the form.
I think this is the easiest and simplest way of checking your spring controller.
Check the extension Advanced REST client here
From what I know You can send JSON object to the webbrowser and it will be displayed without further need of AJAX.
useful tutorial:
http://www.mkyong.com/spring-mvc/spring-3-mvc-and-json-example/

Jersey web service proxy

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).

How servlet handle multiple request from same jsp page

Sorry friends if this question is very easy but i am confuse i unable to find out solution.
As we all know in spring MVC framework we create controller which will handle multiple request from same page using #requestmapping annotation.
but same thing i want to do in servlet how can i do ?
Suppose i have a jsp which which will contain a jqgrid,and two forms i want to use only one servlet to load the data into jqgrid and that servlet only will handle request from both the form . Since we have only doGet and doPost in servlet how one servlet fulfill all three request. Hope you understand my question if you have and link where i get sample or and tutorial link plz reply me
Well, the only easy way to do this would be to use a request parameter to control how the processing happens.
In a very basic example, you may have something like a requestType value that gets passed as either part of the query string or the request body. You would assign values of 1-3 (or 0-2) with each value indicating a different type of request. Your servlet would then parse the request accordingly.
This actually is how the DispatcherServlet in SpringMVC works. There's only one servlet class instance and when a request comes in, it examines the query string along with other parts of the request to determine which controller should handle the request.

Spring Framework HttpRequestHandler failure

We have an application which communicates via REST requests made by clients.
The REST requests contain "region name" and a "ID" as parameters
So, a request would look something like this (for a DELETE)
http://host:port/regionnameID
These REST requests between regions in a federation are properly URL encoded
I find that these request fail if the region name has a slash ("/") in it.
Then, the request would look like so
http://host:port/region/nameID
This is due to incorrect interpretation of the Rest URL by HttpRequesthandler when there is a '/' in the region name.
Now, we have no control over clients sending REST request with "/" in the Region name.
Is there any method / configuration / workaround that can be done to prevent the HttpRequestHandler from returning 404
you should rewrite your urls with urlrwrite and use query parameters internal.
<rule>
<name>Inbound:</name>
<from>^(.*)ID$</from>
<to last="true">delete?regionName=$1</to>
</rule>
Add your urlrewrite Filter in front of all other filters in web.xml
This is a bit of a dirty problem. What I would try to do here is to use the Spring #RequestMapping annotation. There is some documentation on it here:
http://static.springsource.org/spring/docs/2.5.x/reference/mvc.html
You can specific ant wildcards in the value you pass #RequestMapping. If you have a limited number of regions, then you can map them all to a single method as follows:
#RequestMapping(value={"/region1**","/region2**","/region3**")
In your controller method, you will have to add additional logical for parsing out the nameID.
If you have a large number of regions, I would then create a separate Spring Web app (servlet) just to handle these requests. That app would have a cached lookup table of regions.
Configure your own handlerMapping bean (perhaps based on AbstractUrlHandlerMapping)

Categories