Turn off automatic view resolution spring 4 - java

I am using the spring MVC template in IntelliJ to create a webservice to produce JSON from a rest call.
package com.planit.mvc;
#RestController
#RequestMapping("/rest")
public class BasicRestController {
#RequestMapping(value = "/test/{name}", produces = MediaType.APPLICATION_JSON_VALUE)
public Person test(#PathVariable String name) {
Person p = new Person();
p.setAge(10);
p.setFirstName(name);
p.setLastName(name);
return p;
}
}
The servlet dispatcher XML is as follows:
<context:component-scan base-package="com.planit.mvc"/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/"/>
<property name="suffix" value=".jsp"/>
</bean>
So when I navigate to the URL it throws an error as it's trying to resolve a view based on the {name} param of the URL.
What is the correct way to achieve what I am looking, while still allowing for automatic view resolution?
EDIT: When I call the url such as:
http://localhost:8080/rest/test/variable
So hitting the BasicRestController, with the method test due to the /test section of the url, followed by the PathVariable "variable" I get this error in tomcat:
HTTP Status 404 - /WEB-INF/views/rest/test/variable.jsp
So it looks like its trying to resolve the view variable.jsp which of course does not exist. I simply want it to give me back the JSON representation of the Person object, and not have to render it into a view.

I believe you're just missing <mvc:annotation-driven/> from your servlet context configuration. Don't forget to add the namespace declarations and schemaLocation values.

Related

Spring MVC - Using #PathVariable doesn't find the JSP

I am using the #PathVariable annotation to provide an ID to my controller. When I do this, it finds the mapping and runs the code within the controller method, but when it comes to load the JSP it cannot find it and I get the error below.
HTTP ERROR 404
Problem accessing
/Timesheets/viewtimesheet/WEB-INF/pages/viewtimesheet.jsp. Reason:
Not Found
In the log I get the following error:
SEVERE: PWC6117: File "C:\dev\Projects\DominoTimesheets\WebContent\viewtimesheet\WEB-INF\pages\viewtimesheets.jsp" not found
If I take out the #PathVariable then it runs fine and loads the page as expected (but I need to have the timesheetId to runs against the database). The path above has viewtimesheet before the WEB-INF which is causing the issues. It seems that it does not like the mapping of /viewtimesheet/{timesheetID} Can someone shed any light on this?
#RequestMapping(value="/viewtimesheet/{timesheetID}", method = RequestMethod.GET)
public String viewTimesheet(#PathVariable int timesheetID, ModelMap model,
final RedirectAttributes redirectAttributes, HttpSession session) {
Timesheets timesheetResult = timesheetsService.getTimesheet(timesheetID);
model.addAttribute("mondayDate", timesheetResult.getDate_WC());
model.addAttribute("viewTimesheetModel", timesheetResult);
return "viewtimesheets";
}
I have fixed the issue. The InternalResourceViewResolver bean in the dispatcher-servlet required a slash before the prefix value.
<property name="prefix" value="/WEB-INF/pages/"/>
This loaded the page as expected without the extra viewtimesheet in the url:
SEVERE: PWC6117: File
"C:\dev\Projects\DominoTimesheets\WebContent\viewtimesheet\WEB-INF\pages\viewtimesheets.jsp"
not found

Spring MultiPartResolver is manipulating other upload methods

I am trying to merge two Spring based projects into one but I am having an issue with MultiPartResolver. Inside my merged application there are two classes that use uploaded POST methods using different upload methods.
One uses the HttpServletRequest to retrieve the uploaded file :
#RequestMapping(method = RequestMethod.POST)
public #ResponseBody void handleResult(HttpServletRequest request,
HttpServletResponse response)
and the other uses MultipartFile to get the file and another field called notes which is passed to the form:
#RequestMapping(method = RequestMethod.POST)
public #ResponseBody String handleFormUpload(#RequestParam("notes")
String notes, #RequestParam("file") MultipartFile file)
The code then references 'file' to process the uploaded file.
The problem I have is the MultipartFile class requires this in the applicationContext.xml:
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="250000000"/>
</bean>
When this is in the applicationContext.xml file the original Servlet based method of posting fails. The POST request reaches this class but the file seems to have been stripped out as it processes it. As soon as I comment this out of the applicationContext.xml, the servlet method works again. However, the section of the code that uses the MultipartResolver now fails!
I do not have much experience of Spring but I'm trying my best to do this. I cannot work out how to prevent CommonsMultipartResolver from manipulating the POST files that are destined for the Servlet based class.
Can anybody help me?

Model model in Controller's method parameters in Spring MVC

This may be a very naive question to ask but I would like to know as a beginner in Spring MVC framework instead of returning ModelAndView Object can we just return a jsp name from a Controller's method definitions ? Also Apparently all the methods seem to take Model model as a argument. What does they mean ?
#RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Locale locale, Model model) {
logger.debug("Entering renderShoeStoreApplication method");
//model.addAttribute("orderList", orderList);
logger.debug("Exiting renderShoeStoreApplication method");
return "home";
}
Instead of we could also write I suppose
/*
#RequestMapping(value = "/", method = RequestMethod.GET)
public ModelAndView home(Locale locale, Model model) {
logger.debug("Entering renderShoeStoreApplication method");
//model.addAttribute("orderList", orderList);
logger.debug("Exiting renderShoeStoreApplication method");
ModelAndView homeModel = new ModelAndView("home");
return homeModel ;
}*/
Please explain the basics . Thanks in advance.
i think you have got two question
All the methods seem to take Model model as a argument
this is necessarily not required, you can get http request as param and you can derive your model from the request parameters. eventually spring mvc does this for you to make the work much simpler using binding-result after bean validation.
#RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Locale locale, HttpRequest request) {
String name = request.getParamter("name");
// you can manually derive your model here
}
can we just return a jsp name from a Controller's method definitions ?
you can pass the just jsp name in your controller method, provided if you have configured your view resolver to handled this.
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/views/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
if you return string from controller, by default controller direct to view resolver to resolve the view. pls check this SO post
You can go through the below resources to understand the basics of Spring MVC, first and foremost the official docs from spring MVC community and some of the quick heads up of the POC's using below links
http://earldouglas.com/publications/barebones-spring-mvc/
http://spring.io/guides/gs/serving-web-content/
http://www.mkyong.com/tutorials/spring-mvc-tutorials/
Why model is passed as a parameter to controller method and what is the purpose of ModelView object?..All such questions will get answered once you will get the basic understanding of Spring MVC architecture.
And Yes, In the event that there isn't any data to be returned by the method, the controller method can simply return a String that represents the view that should be rendered.

How to register a custom Endpoint Mapping in Spring Soap web services

I'm implementing a SOAP client that interacts with some legacy SOAP services.
All of SOAP body requests have the same format, like this:
<soap:Body>
<execute>
<msg>
</msg>
</execute>
</soap:Body>
As content, the msg element supports a list of any XML tags, so I can send any type of element inside msg: orders, customer, contacts, etc..
All of the requests also have the same action name.
Due to the restrictions/aspects above, if I use spring's PayloadRootAnnotationMethodEndpointMapping, since the root element in the soap body is the same for all the requests, each request will fall in the same method of my Endpoint. If I use spring's SoapActionAnnotationMethodEndpointMapping, since the action is the same for every requests, all of them will fall in the same method again.
The only thing I've got different in the requests, is the requesting URI.
It changes by the name of the operation that I'm invoking. Like:
http://host:port/services/Operation1?Wsdl or
http://host:port/services/Operation2?Wsdl
My idea was to have an endpoint for each type of requests. For example: all request related to products would fit into a "ProductsEndpoint".
I wanted to create a custom endpoint mapping that would extend springs AbstractEndpointMapping. In my implementation I would decide which endpoint to call based on the URI.
But how can I register my custom endpoint mapping in the spring's endpoint mapping chain?
Best regards
If anyone has a request like mine explained above, here goes what I've decided to do...
I've create a class MultipleMarshallersPayloadMethodProcessor extending spring org.springframework.ws.server.endpoint.adapter.method.MarshallingPayloadMethodProcessor. This is the class responsible for marshalling and unmarshalling arguments. In this class I've defined a java.util.map that will associate a given URL to a specific Marshaller. If the current URL request isn't a key in the map, it would use the default Marshaller supplied by the MarshallingPayloadMethodProcessor class.
To register the class as a spring bean:
<bean id="marshallingPayloadMethodProcessor"
class="br.com.tim.fiber.middleware.services.server.helpers.MultipleMarshallersPayloadMethodProcessor">
<constructor-arg ref="defaultMarshaller" />
<property name="otherMarshallers">
<map>
<entry key="/Operation1?wsdl" value-ref="operation1Marshaller"></entry>
<entry key="/Operation2?wsdl" value-ref="operation2Marshaller"></entry>
</map>
</property>
</bean>
And an example of a marshaller:
<bean id="operation1Marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="contextPaths">
<list>
<value>com.app.dtos.operation1</value>
<value>com.app.dtos.common</value>
</list>
</property>
</bean>
With this setup I was able to marshall and unmarshall any request according to the URL. Then I've used the Facade design pattern to create a SOAP Endpoint with a single method that receives all the requests. That method just inspects the URL and delegates to specific endpoints.
#Endpoint
public class FacadeEndpoint {
private static final String NAMESPACE_URI = "http://my.namespace.com/services";
#Autowired
private RequesEndpointURLExtractor requestUrlExtractor;
#Autowired
private OrdersEndpoint ordersEndpoint;
#SuppressWarnings("unchecked")
#PayloadRoot(namespace = NAMESPACE_URI, localPart = "execute")
#ResponsePayload
public ExecuteResponse dispatch(#RequestPayload Execute request) {
String serviceURL = this.requestUrlExtractor.getCurrentURL();
ExecuteResponse response = null;
if (serviceURL.equals(ServiceRequestsEndpoint.CREATE_ENDPOINT_URI)) {
Operation1DTO serviceRequest = (Operation1DTO) request.getMsg().getAnies().get(0);
}
...
}
The RequestEnpointURLExtractor is just a spring bean that extracts the full URL from the request.
#Component
public class RequesEndpointURLExtractor {
public String getCurrentURL() {
TransportContext ctx = TransportContextHolder.getTransportContext();
HttpServletRequest httpServletRequest = ((HttpServletConnection) ctx.getConnection()).getHttpServletRequest();
String pathInfo = httpServletRequest.getPathInfo();
String queryString = httpServletRequest.getQueryString();
return pathInfo + "?" + queryString;
}
}
I could create a custom annotation that would have a URL associated, and use that annotation on methods that would process the request with the URL configured. That would be a cleaner solution instead of the if/else if ladder that I have.
But, since this was only for a simple mockup server, the if/else if ladder isn't such a big deal.

How to match wildcard accept header when using #RequestMapping in Spring framework

I have three resources:
#RequestMapping(value = "sample", method = RequestMethod.GET, headers = "Accept=text/html")
public ResponseEntity<String> sampleResourceHtml()
#RequestMapping(value = "sample", method = RequestMethod.GET, headers = "Accept=application/xml")
public ResponseEntity<String> sampleResourceXml()
#RequestMapping(value = "sample", method = RequestMethod.GET, headers = "Accept=application/json")
public ResponseEntity<String> sampleResourceJson()
When a HTTP client accesses the url with Accept=*/* the webapp returns a 404
In this case I want to invoke sampleResourceHtml()
Changing "Accept=text/html" to "Accept=text/html, */*" will make my webapp accept requests with Accept=*/* which is what I want, however it will also accept requests with Accept=foo/bar which is not what I want.
How do I modify my code to return a supported media type for requests containing wildcards without returning an unexpected media type for unsupported requests?
You might find it easier to configure this in your context with the AnnotationMethodHandlerAdapter, so that the Accept header is automatically handled and the conversion done by Spring and not programmatically.
For example, you could use the following configuration:
<bean id="xstreamMarshaller" class="org.springframework.oxm.xstream.XStreamMarshaller"/>
<bean id="xmlMessageConverter" class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter">
<constructor-arg ref="xstreamMarshaller"/>
</bean>
<bean id="jsonHttpMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"/>
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<util:list>
<ref bean="xmlMessageConverter"/>
<ref bean="jsonHttpMessageConverter"/>
</util:list>
</property>
</bean>
And modify the controller to return the object which Spring will convert to the required type.
#RequestMapping(value = "sample", method = RequestMethod.GET)
public ResponseEntity<String> sampleResource()
Note: You will need the relevant libraries on the classpath.

Categories

Resources