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.
Related
I'm using these graphql dependencies:
"com.graphql-java-kickstart:graphql-spring-boot-starter:12.0.0",
"com.graphql-java-kickstart:graphql-java-tools:12.0.0",
And how can I get httpRequestHeaders from the DataFetchingEnvironment class. I see DataFetchingEnvironment.getContext() is deprecated is there any other alternative?
Current logic:
GraphQLServletContext servletContext = env.getContext(); //deprecated
GraphQLContext qlContext = env.getGraphQlContext(); // No httpRequest
var httpRequest = servletContext.getHttpServletRequest();
You can do:
env.getGraphQlContext().get(HttpServletRequest.class).getHeader("header")
As of 12.0.0, environment.getGraphQLContext() is not supported. This lack of support is referenced in the project's github (https://github.com/graphql-java-kickstart/graphql-spring-boot/issues/808)
As of version 13.0.0, you can access the HttpServletRequest by using
HttpServletRequest httpServletRequest = environment.getGraphQlContext().get(HttpServletRequest.class);
If you need to use version 12.0.0, my suggestion would be to use a OncePerRequestFilter and store the header information you need in a ThreadLocal value. Just remember to clear that thread local value after the request has been processed. This will only work if you turn off "async mode" that the GraphQL library introduced in 11.0.0, as "async mode" processes the request filters and graphql resolvers in different threads.
Upgrade to 13.0.0 (or 14.0.0) and call
HttpServletRequest httpServletRequest = env.getGraphQlContext().get(HttpServletRequest.class);
This will give you and HttpServletRequest, from where you can call
private static Map<String, String> getHeadersFromRequest(HttpServletRequest httpServletRequest) {
var mapOfHeaders = new HashMap<String, String>();
Enumeration<String> headerNames = httpServletRequest.getHeaderNames();
if (headerNames != null) {
while (headerNames.hasMoreElements()) {
String headerName = headerNames.nextElement();
mapOfHeaders.put(headerName, httpServletRequest.getHeader(headerName));
}
}
return mapOfHeaders;
}
to return a list map of headers.
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();
I have a controller mapping, where I pass 2 request params instead of 1. But when done like that Spring is not throwing any exception rather it is ignoring the additional request params.
For eg:
#RequestMapping(value="/test", method = RequestMethod.GET)
public ModelAndView eGiftActivation(#RequestParam("value") String value)
When I hit my app using /test.do?value=abcd it is working fine. But when I pass additional params like /test.do?value=abcd&extra=unwanted also it's working fine.
In this case I want Spring to restrict the second URL where additional params are passed.
How can I achieve this?
You could check it manually, like this:
#RequestMapping("/test")
public ModelAndView eGiftActivation(HttpServletRequest request) {
Map<String, String[]> params = request.getParameterMap();
if (params.size() != 1 || !params.containsKey("value")) {
throw new RuntimeException("Extra parameters are present"); // or do redirect
}
...
}
I don't think it's possible (For Spring to prevent the request to flow to any controller's method). The reason being that:
Your controller handles request based on the URI path like, /app/hello/{name} rather than the request parameters
Request parameters are there to give extra set of meta-info for the request rather than endpoint specification of request.
But, if you wanted to restrict the URI path as such, you can use regex and you can avoid. I'm afraid it's not feasible and even the requirement for that never arose.
Programmatical Way:
Having said that, you can take HttpServletRequest for parameters and loop through the parameters to check for extra ones:
#RequestMapping(value="/test", method = RequestMethod.GET)
public Object eGiftActivation(#RequestParam("value") String value, HttpServletRequest request){
//check the request.getParameterMap() and throw custom exception if you need and handle using Exception handler or throw invalid request
return new ResponseEntity<String>(HttpStatus.SC_BAD_REQUEST);
}
I prefer handling these kind of validations (if required, what ever may be the reason) inside the Filter generically so that the requests will not even reach the Controller methods.
Please find the required code to handle inside the Filter as below (logic is almost similar to Slava).
#Component
public class InvalidParamsRequestFilter extends OncePerRequestFilter {
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
Map<String, String[]> params = request.getParameterMap();
if (request.getRequestURI().contains("/test") && (params.size() != 1 || !params.containsKey("value"))) {
//Here, Send back the Error Response OR Redirect to Error Page
} else {
filterChain.doFilter(request, response);
}
}
}
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 have a J2EE application with a web service which goes like
http://servername/service?task=getFile&id=25
How can I convert these type of urls to
http://servername/service/getFile/25
http://servername/service/getFile/26
etc?
Please provide your suggestions.
You can use the UrlRewriteFilter in order to achieve this. You will just have to write the rules for rewriting, similar to mod_rewrite. For example:
<rule>
<from>^/products/([0-9]+)$</from>
<to>/products/index.jsp?product_id=$1</to>
</rule>
To the point, you thus want to forward the friendly URL to an unfriendly URL (so that you don't need to change existing request parameter collecting logic of the servlet) and to redirect the unfriendly URL to an friendly URL (so that the friendly URL get reflected in the browser address bar of the client).
The best place for this is a Filter. To access the HttpServletRequest, just downcast ServletRequest to HttpServletRequest. You can get the query string by getQueryString() and you can get the pathinfo by getRequestURI(). Here's a kickoff example:
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException
{
HttpServletRequest httpreq = (HttpServletRequest) request;
String query = httpreq.getQueryString();
if (query != null) {
// Unfriendly URL invoked. Convert params to pathinfo and redirect.
StringBuffer newURL = httpreq.getRequestURL();
for (String param : query.split("&")) {
newURL.append('/').append(param.substring(param.indexOf('=') + 1));
}
((HttpServletResponse) response).sendRedirect(newURL.toString());
} else {
// Friendly URL invoked. Convert pathinfo to params and forward.
String[] parts = httpreq.getRequestURI().replace(httpreq.getContextPath(), "").split("/");
String newURL = String.format("%s?task=%s&id=%s", parts[1], parts[2], parts[3]);
httpreq.getRequestDispatcher(newURL).forward(request, response);
}
}
You can of course also grab the aforementioned UrlRewriteFilter.