I'm messing around with Maven/Tomcat/Java in Eclipse. I have made this java servlet, but when I go to localhost:xxxx/myapp/rest I don't get a response on my GET request, I get a 404. I thought if I put the #path to /rest I can send a GET request to the url, but it's not working.
Does anyone know what the issue is? Thank you!
#Path("/rest")
public class WorldResource {
#GET
#Produces("application/json")
public String getOrders() {
WorldService service = ServiceProvider.getWorldService();
JsonArrayBuilder jab = Json.createArrayBuilder();
for (Country o : service.getAllCountries()) {
JsonObjectBuilder job = Json.createObjectBuilder();
job.add("iso2Code", o.getCode());
job.add("iso3Code", o.getIso3Code());
job.add("capital", o.getCapital());
job.add("continent", o.getContinent());
job.add("region", o.getRegion());
job.add("surface", o.getSurface());
job.add("population", o.getPopulation());
job.add("government", o.getGovernment());
job.add("latitude", o.getLatitude());
job.add("longitude", o.getLongitude());
jab.add(job);
}
JsonArray array = jab.build();
System.out.println(array);
return array.toString();
}
}
This is not a servlet, it's a JAX-RS Resource. This will not work "out of the box" within Tomcat, you'll need to deploy a JAX-RS implementation along with it (like Jersey).
A Servlet would look something like this:
#WebServlet(name = "WorldServlet", urlPatterns = {"/rest"})
public class WorldServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("application/json");
try (PrintWriter out = response.getWriter()) {
... // your code
out.println(array.toString());
}
}
}
So, you really just need to look in to installing a JAX-RS provider. Also, when you do that, odds are high it STILL won't be at /rest, because the JAX-RS implementation is normally rooted at some path, so you might end up with something like /resources/rest.
That's all configurable of course.
This can happen because your servlet is incapable of converting your POJO to appropriate HTTP response.
Instead of return array.toString();
try return Response.status(200).entity(array.toString()).build();
Related
I have a GWT application which URL is .../Organizer.html. I would like to access it also from url .../organizer. So I decided to replace the original HttpServletRequest with the wrapper with overriden getRequestURL() and getRequestURI() methods in a servlet filter.
Filter code:
String[] urlSplit = req.getRequestURL().toString().split("/");
String urlEnd = urlSplit[urlSplit.length -1];
if (urlEnd.equals(ORGANIZER_URL_ALTERNATIVE)){
String newUrl = req.getRequestURL().toString().
replace(ORGANIZER_URL_ALTERNATIVE, ORGANIZER_URL);
String newUri = req.getRequestURI().toString().
replace(ORGANIZER_URL_ALTERNATIVE, ORGANIZER_URL);
request = new ChangeUrlRequest(req, newUrl, newUri);
}
//Just to check if it works
req = (HttpServletRequest) request;
System.out.println(req.getRequestURL());
System.out.println(req.getRequestURI());
chain.doFilter(request, response);
Request wrapper:
class ChangeUrlRequest extends HttpServletRequestWrapper {
private StringBuffer newUrlBuffer;
private String newUri;
public ChangeUrlRequest(HttpServletRequest request,String newUrl, String newUri) {
super(request);
newUrlBuffer = new StringBuffer(newUrl);
this.newUri = newUri;
}
#Override
public StringBuffer getRequestURL() {
return newUrlBuffer;
}
#Override
public String getRequestURI() {
return newUri;
}
}
This works as expected in way that I can use .../organizer and is replaced by .../Organizer.html
The problem I have now is that even if the URL/URI is the same whether I access .../organizer or .../Organizer.html from browser, only the .../Organizer.html works and for .../organizer the Tomcat complains it cannot find the page: HTTP Status 404 - /my-page/Organizer.html
The output of System.out from the code above:
with Organizer.html (works):
URL: http://localhost:8080/my-page/Organizer.html
URI: /my-page/Organizer.html
with organizer (gives above mentiond 404):
URL: http://localhost:8080/my-page/Organizer.html
URI: /my-page/Organizer.html
Do I need to override or change also something else?
If the goal is to be able to access the app by either URL, maybe there is a simpler solution. You could write a servlet accessible at /organizer and forward the request to the HTML page, e.g.:
#WebServlet(urlPatterns="/organizer")
public class OrganizerServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) {
RequestDispatcher dispatcher = getServletContext().getRequestDispatcher("/Organizer.html");
dispatcher.forward(request,response);
}
}
Note that you may need to modify the paths for /organizer and /Organizer.html if they are not at the root of your application.
I have developed a custom tag library in Java which I use in my web application.
I am not sure why but my doTag() is not setting up cookie at all. I have cleared my cache and restarted my computer as well. Here is the code:
public class UserVersionOfSite extends EvenSimplerTagSupport {
private static final Log logger = LogFactory.getLog(UserVersionOfSite.class);
private StringWriter sw = new StringWriter();
#Override
public void doTag() throws IOException, JspException {
getJspBody().invoke(sw); //get the tag body and put it in StringWriter object
//get request object to get cookie value
PageContext ctx = (PageContext)getJspContext();
HttpServletRequest httpServletRequest = (HttpServletRequest) ctx.getRequest();
HttpServletResponse httpServletResponse = (HttpServletResponse) ctx.getResponse();
if(httpServletRequest.getParameterMap().containsKey("show_full_site")) {
logger.debug("show_full_site ");
if(!checkIfCookieExists(httpServletRequest)){
Cookie cookie = new Cookie("SHOW_FULL_SITE",httpServletRequest.getParameter("show_full_site"));
cookie.setMaxAge(86400);
httpServletResponse.addCookie(cookie);
//write the tag output
if(!httpServletRequest.getParameter("show_full_site").equalsIgnoreCase("true")){
//write the response
getJspContext().getOut().println(sw.toString());
}
}else{
String cookieValueString = getCookieValue(httpServletRequest.getCookies(),"SHOW_FULL_SITE","false");
if(!cookieValueString.equalsIgnoreCase("true")){
//write the response
getJspContext().getOut().println(sw.toString());
}
}
}
}
#Override
public String getResult() throws IOException {
return "User version of site";
}
public String getCookieValue(Cookie[] cookies,
String cookieName,
String defaultValue) {
for(int i=0; i<cookies.length; i++) {
Cookie cookie = cookies[i];
if (cookieName.equals(cookie.getName()))
return(cookie.getValue());
}
return(defaultValue);
}
public boolean checkIfCookieExists(HttpServletRequest httpServletRequest){
logger.debug("inside checkIfCookieExists()");
boolean cookiePresent = Arrays.asList(httpServletRequest.getCookies()).contains( "SHOW_FULL_SITE" );
return cookiePresent;
}
}
Even I tried adding the code without using if else statements but still no success. Is there any thing critical I am missing?
Any ideas guys??!!! I have checked the browser's setting as well, but there is nothing there which is blocking a creation of cookie!
I realise the horse has probably bolted by the time I'm posting this but, for the benefit of others stumbling across it, I think the problem may be related to the feature of RequestDispatcher highlighted in this question: unable to add a cookie included in JSP via jsp:include
your following line inside checkIfCookieExists() method is wrong:
Arrays.asList(httpServletRequest.getCookies()).contains( "SHOW_FULL_SITE" );
HttpServletRequest.getCookies() returns Cookie[]. You are wrapping it inside a List and checking for a string "SHOW_FULL_SITE" inside this.
Coming back to your question- how do you know cookie is not being set in the HTTP headers? Try using browser plugins like firebug to see the HTTP response headers coming from server. Also set the path of cookie before adding it to response e.g.
Cookie cookie = new Cookie("SHOW_FULL_SITE",httpServletRequest.getParameter("show_full_site"));
cookie.setMaxAge(86400);
cookie.setPath("/");
I've a method that uses HttpServletRequest, HttpServletResponse and ServletContext.
Here's my code:
public String processarModelo(MyObject ou, Map<String, Object> attrs,
Map<String, Object> params) throws Exception {
ServletContext sc = com.opensymphony.webwork.ServletActionContext.getServletContext();
HttpServletResponse r = com.opensymphony.webwork.ServletActionContext.getResponse();
MyHttpRequest rw = new MyHttpRequest(com.opensymphony.webwork.ServletActionContext.getRequest());
rw.clearAttributes();
for (String s : attrs.keySet()) {
rw.setAttribute(s, attrs.get(s));
}
Map<String, String> p = rw.getParameterMap();
p.clear();
for (String s : params.keySet()) {
p.put(s, (String) params.get(s));
}
ByteArrayOutputStream bout = new ByteArrayOutputStream();
Writer w = new OutputStreamWriter(bout);
SwallowingHttpServletResponse r2 = new SwallowingHttpServletResponse(r, w, "iso-8859-1");
javax.servlet.RequestDispatcher dispatcher = sc.getRequestDispatcher("/paginas/expediente/processa_modelo.jsp");
dispatcher.include(rw, r2);
w.flush();
String s = bout.toString();
return s;
}
It's working when I call it from my browser.
This week I've built a webservice that must call the same method. Inside the webservice method I have however no ServletContext, HttpServletResponse and HttpServletRequest at hands.
How can I emulate them to render my JSP and get the generated HTML?
Well, searching around about #Context annotation, i found this one for webservice:
#Resource
private WebServiceContext context;
With this, i can get everything i need with this:
HttpServletRequest request = (HttpServletRequest)context.getMessageContext().get(MessageContext.SERVLET_REQUEST);
ServletContext servletContext = (ServletContext) context.getMessageContext().get(MessageContext.SERVLET_CONTEXT);
HttpServletResponse response = (HttpServletResponse) context.getMessageContext().get(MessageContext.SERVLET_RESPONSE);
Thanks everybody for helping!!
Are you sure you want your web service to call this? It will get redirected to some other page....
It looks like a design issue to me. You should extract the actual functionality from here and place it in some common code. Then call it in such a way that the web service request and servlet request will have enough information to call the functionality.
Also one letter variable names are discouraged ;)
If you want to make a call to the web page to store the HTML, you should make an HTTP request in the webservice method itself and store the data. You can use something like HTTPClient (http://hc.apache.org/httpcomponents-client-ga/) to do this.
Trying to build the HTTPRequest yourself isnt a good way to go.
Oh hello there, fellow SO members,
I have a web service that returns XML data using a simple get request that goes like this :
http://my-service:8082/qc/getData?paramX=0169¶mY=2
the service returns raw xml in the page according to the parameters' values.
I am trying to retrieve this data from a GET request in GWT using RequestBuilder, Request, etc.
However, the response gives me empty text, a Status code of ZERO (which doesn't mean anything and isn't supposed to happen), and so on.
Here's the simplified code that doesn't work.
public class SimpleXML implements EntryPoint {
public void onModuleLoad() {
this.doGet("http://my-service:8082/qc/getData", "0169", "2");
}
public void doGet(String serviceURL, String paramX, String paramY) {
final String getUrl = serviceURL + "?paramX=" + paramX + "&idTarification=" + paramY;
RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, getUrl);
try {
Request response = builder.sendRequest(null, new RequestCallback() {
#Override
public void onResponseReceived(Request request, Response response) {
response.getStatusCode(); // Gives me 0 (zero) :(
}
#Override
public void onError(Request request, Throwable exception) {
// ... doesn't matter for this example
}
});
} catch (RequestException e) {
// ... doesn't matter for this example
}
}
}
I don't get why this wouldn't work, since this is REALLY simple, I've seen tutorials and they all show me this way of doing things..
Thanks in advance
The reason is, that browsers do not allow cross-site requests with AJAX (see Same Origin Policy).
This means, that you can only call a service on the same server, same port (using the same protocol) as your HTML page. If you want to perform cross-site requests, you can use JSONP, as explained in http://code.google.com/webtoolkit/doc/latest/tutorial/Xsite.html.
Forgive me, but I may not be familiar with all the lingo necessary to ask this question properly.
I'm working on a fairly simple REST web service in Java using the org.apache.cxf.jaxrs.ext implementation of jax-rs. The method header is like this:
#GET
#Path("json/{fullAlias}")
#Produces({"application/json"})
public String json(#PathParam("fullAlias") String fullAlias, #Context MessageContext req)
where MessageContext is org.apache.cxf.jaxrs.ext.MessageContext.
There are two things I'm trying to accomplish that I can't seem to figure out:
Change the content-type if certain conditions are met (e.g. for an error)
Change the status code of the response
I've tried using changing the response by accessing it through the MessageContext:
HttpServletResponse response = req.getHttpServletResponse();
response.setContentType("text/plain")
response.setStatus("HttpServletResponse.SC_BAD_REQUEST);
But these changes have no bearing on the response sent; with or without the #Produces annotation, setting the content type inside the method doesn't affect the actual content type (With the annotation, it of course returns "application/json", without it defaults to "text/html").
I am returning a simple String as the body. I've entertained trying to return a javax.ws.rs.core.Response object to do what I want, but I don't know much about it.
How would I change the content type and/or the status codes from inside this method?
One approach is to throw a WebApplicationException, as described by Pace, which will work if you are looking to specifically handle an error condition. If you are looking to be able to change your content at any time for any reason, then you will want to take a look at returning a Response as the result of your service method rather than a String. Returning a Response gives you the greatest amount of control over how your service responds to the client request (it does require more code than returning a simple string).
Here is an example of how you would can make use of the Response object:
#GET
#Path("json/{fullAlias}")
public Response json(#PathParam("fullAlias") String fullAlias, #Context MessageContext req) {
...
if (success) {
ResponseBuilder rBuild = Response.ok(responseData, MediaType.APPLICATION_JSON);
return rBuild.build();
}
else {
ResponseBuilder rBuild = Response.status(Response.Status.BAD_REQUEST);
return rBuild.type(MediaType.TEXT_PLAIN)
.entity("error message")
.build();
}
}
I'm not sure if it's the best approach but I've done the following to solve your question #1.
public WebApplicationException createStatusException(String statusMessage) {
ResponseBuilder rb = Response.noContent();
rb = rb.type(MediaType.TEXT_PLAIN);
rb = rb.status(Status.BAD_REQUEST);
rb = rb.entity(statusMessage);
return new WebApplicationException(rb.build());
}
EDIT: I then threw the resulting WebApplicationException.
You can write your own Response Filter to change the content-type header.
#Provider
public class MimeAddingFilter implements ContainerResponseFilter {
#Override
public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext)
throws IOException {
responseContext.getHeaders().add("Content-Type", "image/png");
}
}
This filter will add the "image/png" content-type header. You can also change or remove headers in JAX-RS response filters.