I am working with Spring MVC3.2 and I have a registration form(http://my-server.com:8080/tracks/apks). Users post it to the server and the server will return error message when validation fails. But I got the error message from the server, the URL was different from what I wanted. Here is my code:
Web.xml
<servlet-mapping>
<servlet-name>tracks</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
applicationContext.xml
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/pages/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
#Controller
#RequestMapping("/apks")
public class ApkController {
#RequestMapping()
public ModelAndView index() {
Map<String, Object> modelMap = new HashMap<String, Object>();
modelMap.put("menus", AdminService.getMenus("apks"));
return new ModelAndView("apks", "model", modelMap);
}
#RequestMapping(value = "/insert", method = RequestMethod.POST)
public ModelAndView uploadApk(ApkInfo apkInfo, BindingResult bindingResult) {
Map<String, Object> modelMap = new HashMap<String, Object>();
modelMap.put("menus", AdminService.getMenus("apks"));
if (!fileExists(apk.getFileName())){
modelMap.put("message", message);
}
//Do something
return new ModelAndView("apks", "model", modelMap);
}
After calling uploadApk, I expected http://my-server.com:8080/tracks/apks but The returned URL was http://my-server.com:8080/tracks/apks/insert.
What do I do to fix it?
Thanks in advance.
Couple of observation.
In your web.xml, do you specify context-paran, the servlet tracks and the listener?
Is context:component-scan enabled in your spring configuration file?
Use requestMapping at method level to map request to specific method.
What does 'The returned URL' mean?
You should access 'http://my-server.com:8080/apks/insert' to call 'uploadApk' method
cause you have
#RequestMapping("/apks")
on your controller and
#RequestMapping(value = "/insert", method = RequestMethod.POST)
on your 'uploadApk' method.
How did you call the 'uploadApk' method?
I think that you should explain about it more to get an appropriate answer.
Since the url-pattern of servlet-mapping in your web.xml is '/',
you should remove '/tracks' in your url.
'tracks' is just a servlet name and not a servlet path.
So if you access to /tracks/apks/insert then you will got an 404 error.
Access to /apks/insert instead.
I guess that you may want a redirection after calling 'uploadApk' method
cause you attached 'redirect' tag on your question and used the word 'returned URL'. (Right?)
If my guess is right and you want to redirect the browser, then see SpringMVC 3.2 Redirect View docs.
Use below codes to redirect.
return new RedirectView("url-you-want");
or
return "redirect:url-you-want"
Related
I am trying to access following sling servlet using http://localhost:4502/sling/test-services/planet.html
But, it is giving 404 error, not sure what I am doing wrong here.
#Component
#Service(value=javax.servlet.Servlet.class)
#Properties({
#Property(name="service.description", value="HTML renderer for Planet resources"),
#Property(name="service.vendor", value="The Apache Software Foundation"),
#Property(name="sling.servlet.resourceTypes", value="sling/test-services/planet"),
#Property(name="sling.servlet.extensions", value="html"),
#Property(name="sling.servlet.methods", value="GET")
})
#SuppressWarnings("serial")
public class PlanetResourceRenderingServlet extends SlingSafeMethodsServlet {
#Override
protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html");
response.setCharacterEncoding("UTF-8");
final ValueMap properties = request.getResource().adaptTo(ValueMap.class);
// TODO should escape output - good enough for our tests
final PrintWriter pw = response.getWriter();
pw.println(String.format("<html><head><title>Planet at %s</title></head><body>", request.getResource().getPath()));
pw.println(String.format("<p>Name: %s</p>", properties.get("name")));
pw.println(String.format("<p>Distance: %s</p>", properties.get("distance")));
pw.println("</body></html>");
pw.flush();
}
}
Is it possible, I could access the servlet service without ".html" extension, if I remove extension property?
I appreciate any help.
Thank you!
When you want to access a servlet through an URL you need to set the sling.servlet.paths instead of the sling.servlet.resourceTypes. A similar issue has been answered here.
If you are setting the sling.servlet.resourceTypes property, then you need to access a resource whose sling:resourceType is sling/test-services/planet.
Your annotations should be
#Component
#Service(value=javax.servlet.Servlet.class)
#Properties({
#Property(name="service.description", value="HTML renderer for Planet resources"),
#Property(name="service.vendor", value="The Apache Software Foundation"),
#Property(name="sling.servlet.paths", value="/sling/test-services/planet"),
#Property(name="sling.servlet.extensions", value="html"),
#Property(name="sling.servlet.methods", value="GET")
})
Or this can be further simplified using the #SlingServlet annotation as shown below
#SlingServlet(paths="/sling/test-services/planet", methods="GET", extensions="html")
Make sure that you allow the following path is allowed in Apache Sling Servlet/Script Resolver and Error Handler configuration available in OSGi console.
I'm new to Spring MVC Restful.
Suppose I have index.jsp which forwards user to a form page where user could submit a term to search. I catch the term with a POST handler method, and then do some calculation and hope to redirect the result to be used at another page (/WEB-INF/jsp), for example, we say build a graph based on the result. The problem is how to gather the results and redirect the URL at the same time.
The Controllers like below:
#RequestMapping(value="/termForm", method = RequestMethod.GET)
public ModelAndView setupForm() {
Term termClass = new Term();
return new ModelAndView("term", "command", termClass);
}
#RequestMapping(value="/getTerm", method=RequestMethod.POST)
public String getTerms(#ModelAttribute("term") Term term, BindingResult result)
{
String label = term.getTerm();
//doing some calculation to term here
result = ....
return "redirect:"+ "graphPage.jsp";
}
By searching, I found that Spring View Resolver only could process the redirected jsp under root directory (as same with index.jsp). In this case, the "result" seems not accepted by "graphPage". I also included UrlBasedViewResolver in XXX-servlet.xml as following:
<bean id="viewResolver"
class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
Sorry for the long question, please give any hint to do this. Thanks a lot.
There are two parts of my question. One is redirecting POST method to another page, graphPage.jsp. Since we go to graph, we need the data from POST method as well to create graph. This is the other concern. Hope it's clear. I already solved the first one by adding a handler method, see below. But how to package the result and pass it to Graph.jsp? Thanks
#RequestMapping(value="/graphPage", method=RequestMethod.GET)
public String showGraph()
{
return "graphPage";
}
You will get a better controll over the redirect if you use the RedirectView instead of the String. See this example.
#Contoller
#RequestMapping("/your")
public class YourController
#RequestMapping(value="/getTerm", method=RequestMethod.POST)
public ModelAndView getTerms(#ModelAttribute("term") Term term, BindingResult result) {
...
return new ModelAndView(new RedirectView("/your/other", true));
}
#RequestMapping(value="/other", method=RequestMethod.POST)
public String otherMethod() {...}
}
But maybe you asked something different, then please rewrite your question. It is very hard to understand what your problem is./
BTW. test that you can request your "graphPage" directly
I am creating a JAX-RS based web service in CXF and I want to get the parameters passed to the method in the RequestHandler registered as a <jaxrs:provider>.
I want the parameter name and corresponding value in the handler and here is my code:
public class SampleRequestHandler implements RequestHandler {
#Override
public Response handleRequest(Message arg0, ClassResourceInfo arg1) {
OperationResourceInfo resourceInfo = arg0.getExchange().get(OperationResourceInfo.class);
String name = resourceInfo.getMethodToInvoke().getName();
return null;
}
}
My JAX-RS based service:
#Service("bookService")
#Path("/bookstore")
public class BookStore {
#POST
#Path("/books")
#Produces({ "application/xml" })
#Consumes({ "application/xml" })
public Book addBook(Book book) {
return book;
}
}
and my beans.xml where I have registered the handler and restful service:
<context:component-scan base-package="com.tutorial.cxf.jaxrs.service"/>
<bean id="sampleHandler" class="com.tutorial.cxf.jaxrs.interceptors.SampleRequestHandler"/>
<jaxrs:server id="restContainer" address="/">
<jaxrs:serviceBeans>
<ref bean="bookService"/>
</jaxrs:serviceBeans>
<jaxrs:providers>
<ref bean="sampleHandler"/>
</jaxrs:providers>
</jaxrs:server>
Anybody already manage this case?
I had the same issue when trying to take the method with:
List<Parameter> params = ori.getParameters();
It only returns the parameter's name (the one declared in the method) but not the values.
The official CXF documentation shows only a little about it, but as explained you can always take the QUERY_STRING value of the message and parse it.
You can do something like this in your handler/filter:
String queryString = (String) arg0.get(Message.QUERY_STRING);
MultivaluedMap<String, String> queryMap = JAXRSUtils.getStructuredParams(queryString, "&", false, false);
and after loop over the queryMap collection. The map will contains all of your query parameters, even those who are not declared in the Rest method of your BookStore class.
Previously, when I used Jersey on Grizzly, if I called an HTTP method that was not defined in Jersey annotations, it would return a 405 Method Not Allowed response and this was fine.
Now that I am running Jersey on Tomcat, the server returns Tomcat's specific 405 html page. How can I revert to simply sending the response with an empty body?
As taken from this thread: http://jersey.576304.n2.nabble.com/how-to-catch-405-errors-td4937392.html
Create an exception mapper class like so:
#Provider
public class MyMapper implements
ExceptionMapper<WebApplicationException> {
public Response toResponse(WebApplicationException e) {
Response r = e.getResponse();
if (r.getStatus() == 405) {
return Response.fromResponse(r).entity(...).build();
}
return r;
}
}
This allowed me to capture a 405 request and return a more helpful error resource that can be parsed by applications.
You can configure a custom page in your webapp's web.xml:
<error-page>
<error-code>405</error-code>
<location>/empty.txt</location>
</error-page>
Location can refer to an empty text file or JSP/Servlet/whatever fits your needs.
My custom exception I was returning an Error object (POJO) in the Response...and my servlet server didn't know how to convert Error to JSON.
I solved the problem by adding the following maven dependency:
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-moxy</artifactId>
<version>2.27</version>
</dependency>
And my response like this:
#Override
public Response toResponse(WebApplicationException e) {
Response r = e.getResponse();
if (r.getStatus() == 405) {
Error error = new Error(Response.Status.BAD_REQUEST.toString(), e.getMessage());
return Response.fromResponse(r).status(Response.Status.BAD_REQUEST).header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON)
.entity(error)
.build();
}
return r;
}}
Actually the part which did the trick was:
header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON)
I have to map a REST Webservice URL like "http://server:8080/application/service/customer/v1"
to createCustomer method in CreateCustomerBean class..
I have done the following mappings..
*Web.xml*
<servlet-mapping>
<servlet-name>RestiveServlet</servlet-name>
<url-pattern>/service/*</url-pattern>
</servlet-mapping>
*Rest-Config.xml*
<jaxrs:server address="/customer/"
<jaxrs:serviceBean>
<ref bean="CreateCustomerBean"/>
</jaxrs:serviceBean>
</jaxrs:server>
Now the problem is the remaining path of the url("http://server:8080/application/service/customer/v1") is v1 rest all is mapped and i have to specify 2 #Path attributes one at the CreateCustomerBean class level and one at the createCustomer method in that bean.. so i have to append "create" before v1 .. and the url becomes
#Path (/create/)
CreateCustomerBean{
#Path(/v1)
createClient(String request){
}
}
http://server:8080/application/service/customer/create/v1/ which i dont want.. is there any way to avoid the #Path attribute at the class level and direct all the request to the createCustomer method.
In you code you can re-write code like this
#Path ("/v1")
CreateCustomerBean{
#Post
createClient(String request){ }
}
As long as you specify the POST attribute all the post request should be re-directed to the respective method.
Hope it helps.
Cheers