REST request to JAVA Servlet - java

I have some JavaScript which I want to perform a REST Request (GET) to my servlet.
The format of the record I want to send is in the following format ...
/id1/vara/varb/varc/timedelta1,timedelta2,timedelta3,....,timedeltaN/
So basically there would be 5 attributes in each record I send. I need to batch these up - I'm sending multiple records in a single GET Request. My Get URL might look a little like the following.
myservletname/id1/vara/varb/varc/timedelta1,timedelta2,timedelta3/id2/vara/varb/varc/timedelta1,timedelta2,timedelta3/id3/vara/varb/varc/timedelta1,timedelta2,timedelta3/
I'm aware on the limit of around 2000 chars in the URL String so to keep things safe I'll ensure the length of the URL is less than this.
In the above example 3 records were sent to the servlet.
I'm wondering how I might process these on the server end. Havent really worked with REST before in Java. What do I need to do on the server end to process these URLs to extract the data ?
Thanks

Basically
public class RestServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) {
String uri = request.getPathInfo();
Pattern p = Pattern.compile(
"/([^/]+)/([^/]+)/([^/]+)/([^/]+)/(\d+)(?:,(\d+))*/"
);
Matcher m = p.matcher(uri);
if (m.matches()) {
String id = m.group(1);
String vara = m.group(2);
String varb = m.group(3);
String deltas = m.group(4);
// etc
}
}
}
It's not a very good model for how to do it, but it is simple and understandable for someone not familiar with Servlets

You can use JAX-RS or Restlets instead of a servlet

You should seriously consider using POST instead of GET for this. REST (and URLs) weren't designed for this purpose.

Related

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)

HttpServletRequest getParameter unable to retrieve parameters with &

I have a url, something like this localhost:8080/foo.action?param1=7&param2=8&param3=6
When this is the Url (as it is), request.getParmeter("param2") gives me 8 [Correct]
i) When the encoding converts this url to localhost:8080/foo.action?param1=7%26param2=8%26param3=6
In this case, request.getParameter("param1") gives me 7&param2=8&param3=6
ii) When the encoding converts this url to localhost:8080/foo.action?param1=7&param2=8&param3=6
In this case, request.getParameter("param1") gives me 7 and request.getParameter("param2") gives me null
What is the correct way of retrieving the parameters? [Assuming that using one of the two Url encoding schemes is unavoidable]
(I am using struts actions)
To prevent this do not encode parameters with delimeters, encode only parameters values. This will be the best way. If you cannot handle parameters encoding just do decoding on server side before parsing:
String queryString = request.getQueryString();
String decoded = URLDecoder.decode(queryString, "UTF-8");
String[] pares = decoded.split("&");
Map<String, String> parameters = new HashMap<String, String>();
for(String pare : pares) {
String[] nameAndValue = pare.split("=");
parameters.put(nameAndValue[0], nameAndValue[1]);
}
// Now you can get your parameter:
String valueOfParam2 = parameters.get("param2");
You can call req.getQueryString() to get the whole query parameters and then do server side decoding based on whatever encoding methods you choose.
Try using
String[] Parameters = = URLDecoder.decode(Request.getQueryString(), 'UTF-8').splitat('&') ;
Hope this helps.
I had this happen to me today. Turns out I was passing the encoded url over the wire. When the request is made it should be made as http://localhost/foo?bar=1&bat=2 not as http://localhost/foo?bar=1&bat=2.
In this case I had cut the url from an xml file and pasted it into a browser.

How should I send the response in Servlet to Front end?

I have written a Servlet something like this
public class ServletUtil extends HttpServlet {
private static final long serialVersionUID = 1571172240732862415L;
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
String acInfo = request.getQueryString();
someDao dao = new someDao();
ArrayList<String> resultAutoComplete=dao.someResults(acInfo);
out.close();
}
}
I have an auto complete Object/wizard in front end and as the user types in it is making Ajax call to back end to grab the list of results. So I have written a Servlet and I am pulling the user input and getting my results from DAO layer.
My question here is how should I send this list(resultAutoComplete) to Front end in the Servlet?
I'd expect you to serialise this in some fashion such that the client understands it. e.g. perhaps using JSON or similar.
I note that your response content type is text/html. So why not simply write each element of your list to your Writer out, separated by (say) a <li> element (with the appropriate unordered/order list entities surrounding this)
Try this,
for (String str : resultAutoComplete)
{
out.println(str);
}
By serializing it to a String and writing it to out...
Seriously though, I wouldn't code at the low level Servlet spec. For this kind of return-this-pojo call I would use Spring 3's RESTful service libraries, or something similar.
No json! instead of going through a list in javascript, return a completed <li> lists and replace innerHTML of <ul>.The reason to do so is to give a better performance. Unless you want to do something more flexible, leave things to the back-end.
When do json, you gotta parse string into json object and then loop through and generate html, that's just an extra step. Keep things simple, plus, parsing string could be costly.
If you don't loop through the list and instead do out.println the list object, you would likely see the address. also, you need to generate html, so:
StringBuilder sb = new StringBuilder();
for(String option: options){
sb.append("<li>").append(option).append("</li>");
}
out.println(sb);

Java: How to easily check if a URL was already shortened?

If I have a general url (not restricted to twitter or google) like this:
http://t.co/y4o14bI
is there an easy way to check if this url is shortened?
In the above case, I as a human can of course see that it was shortend, but is there an automatic and elegant way?
You could do a request to the URL, look if you get redirected and if so, assume it's a shortening service. For this you'd have to read the HTTP status codes.
On the other hand, you could whitelist some URL shortening services (t.co, bit.ly, and so on) and assume all links to those domains are shortened.
Drawback of the first method is that it isn't certain, some sites use redirects internally. The drawback of the second method is that you'd have to keep adding shortening services, although only a few are used widely.
One signal may be to request the URL and see if it results in a redirect to another domain. However, without a good definition of what "shortened" means, there is no generic way.
if you know all the domains that can be used to shorten your URLs, check if it is contained :
String[] domains = {"bit.ly", "t.co"...};
for(String domain : domains){
if(url.startsWith("http://" + domain)){
return true;
}
}
return false;
You can't: You will have to work by assumption.
Assumption:
Does www exist in url.
Does the server name end with a valid domain (e.g. com, edu, etc.) or does it has co.xx where xx is a valid country or organization code.
And you can add more assumption based on other url shortening links.
You can't.
You can only check if you list a couple of shorteners and check if the url starts with it.
You can also try checking whether the url is shorter than a given length (and contains path/query string), but some shorteners (tinyurl for example) may have longer urls than normal sites (aol.com)
I would prefer the list of known shorteners.
Here's what you could do in Java, groovy and the like.
Get the url you want to test;
Open the url with HttpURLConnection
Check the response code
if it is a valid code, 200 for example, the you can retrieve the url string in long form from the connection object if it was shortened or back in its original form if it wasn't.
We all love to see some code don't we. Its crude, but hey!
String addr = "http://t.co/y4o14bI";
URL url = new URL(addr);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
if (connection.getResponseCode() == 200) {
String longUrl = connection.url;
System.out.println(longUrl);
} else {
// You decide what you want to do here!
}
Actually, you as a human, can't. The only way you know that it's shortened is that it's a t.co domain. The y4o14bI could be an CMS identifier for all you know.
The best way would be to use a list of known shortener urls, and lookup against that.
And even then you would have problems. I use bit.ly with a personal domain, wtn.gd
So http://wtn.gd/random would also be a shortened URL.
You could maybe do a HTTP HEAD-request, and check for a 301/302 ?
If you request an URL like this, your HttpCLient should receive a HTTP Redirect instead of a HTML page. This wouldn't be an evidence but at least a hint.
Evaluate the URL and look for some clues:
the Path meets certain criteria
only has one step (i.e. not multiple slashes)
does not end with filename extensions
not longer than X characters (would need to evaluate various URL shortening services and adjust the upper bounds for the max token length)
HttpUrlConnection returns a redirect responseCode (i.e. 301, 302)
I would suggest using android.util.Patterns.WEB_URL
public static List<String> findUrls(String input) {
List<String> links = new ArrayList<>();
Matcher m = android.util.Patterns.WEB_URL.matcher(input);
while (m.find()) {
String url = m.group();
links.add(url);
}
return links;
}
Use the unshorten URL service like https://unshorten.me
They have an API as well https://unshorten.me/api
If the URL is shortened it will return the original URL.
If not you will get the same one back.

How to send parameters from a servlet

I am trying to use a RequestDispatcher to send parameters from a servlet.
Here is my servlet code:
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String station = request.getParameter("station");
String insDate = request.getParameter("insDate");
//test line
String test = "/response2.jsp?myStation=5";
RequestDispatcher rd;
if (station.isEmpty()) {
rd = getServletContext().getRequestDispatcher("/response1.jsp");
} else {
rd = getServletContext().getRequestDispatcher(test);
}
rd.forward(request, response);
}
Here is my jsp, with the code to read the value - however it shows null.
<h1>response 2</h1>
<p>
<%=request.getAttribute("myStation") %>
</p>
Thanks for any suggestions.
Greener
In your servlet use request.setAttribute in the following manner
request.setAttribute("myStation", value);
where value happens to be the object you want to read later.
and extract it later in a different servlet/jsp using request.getAttribute as
String value = (String)request.getAttribute("myStation")
or
<%= request.getAttribute("myStation")%>
Do note that the scope of usage of get/setAttribute is limited in nature - attributes are reset between requests. If you intend to store values for longer, you should use the session or application context, or better a database.
Attributes are different from parameters, in that the client never sets attributes. Attributes are more or less used by developers to transfer state from one servlet/JSP to another. So you should use getParameter (there is no setParameter) to extract data from a request, set attributes if needed using setAttribute, forward the request internally using RequestDispatcher and extract the attributes using getAttribute.
Use getParameter(). An attribute is set and read internally within the application.
In your code,
String test = "/response2.jsp?myStation=5";
You are adding myStation=5 as query string.As the query string parameters are stored
as request parameters in Request Object.
Therefore you can use ,
It works fine.Thanks.

Categories