spring-mvc: error mapping url for form controller - spring-mvc

i have a problem with spring mvc
my spring bean
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean
class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping" />
<bean id="urlMapping"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="welcome.htm">welcomeController</prop>
</props>
</property>
</bean>
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
<bean name="welcomeController"
class="org.springframework.web.servlet.mvc.ParameterizableViewController"
p:viewName="welcome" />
<bean name="/bscList.htm" class="cbs.web.BscController">
<property name="bscDao" ref="myBscDao" />
</bean>
<bean name="/bscForm.htm" class="cbs.web.BscFormController">
<property name="commandName" value="bsc"/>
<property name="commandClass" value="cbs.domain.Bsc"/>
<property name="formView" value="bscForm"/>
<property name="successView" value="bscList.htm"/>
<property name="bscDao" ref="myBscDao"/>
</bean>
</beans>
my form controller
public class BscFormController extends SimpleFormController {
private static Logger log = Logger.getLogger(BscController.class);
private BscDao bscDao;
public void setBscDao(BscDao bscDao) {
this.bscDao = bscDao;
}
protected Object formBackingObject(HttpServletRequest request)
throws Exception {
String id = request.getParameter("id");
if (!StringUtils.isBlank(id)) {
return bscDao.get(new Integer(id));
}
return new Bsc();
}
public ModelAndView onSubmit(HttpServletRequest request,
HttpServletResponse response, Object command, BindException errors)
throws Exception {
log.debug("entering 'onSubmit' method...");
Bsc bsc = (Bsc) command;
String success = getSuccessView();
if (request.getParameter("delete") != null) {
bscDao.remove(bsc.getId());
} else {
bscDao.save(bsc);
}
return new ModelAndView(success);
}
}
my problem:
when I access /bscList.htm, it's display list of bsc (bscList.jsp template),
but when I access /bscForm.htm, it's still display bsc's list, not show my form (bscForm.jsp template)
I have test with some simple controller:
controller implement org.springframework.web.servlet.mvc.Controller, evething run fine
controller extends SimpleFormController, map error:
No mapping found for HTTP request with URI [/cbs/testform.htm] in DispatcherServlet with name 'dispatcher'

when i use HandlerMapping ControllerClassNameHandlerMapping, all request URL '/bsc*' will map to BscController (/bscForm.htm will not map to BscFormController)

Related

Can an abstract class extend JdbcDaoSupport/NamedParameterJdbcDaoSupport in Spring MVC?

I'm trying to implement a Spring MVC web-app (using Spring-FW-ver: 4.3.1). And my web-app's DAO layer architecture is as follows :-
//1. BaseDAO interface
public interface BaseDAO {
//abstract methods
}
//2. BaseDAOJdbcImpl.java file - an abstract DAO class for common method(s) which other sub-DAO classes can inherit
#Repository
public abstract class BaseDAOJdbcImpl extends NamedParameterJdbcDaoSupport implements BaseDAO
{
// implementations of above BaseDAO abstract methods
}
//3. UserDAO interface that extends BaseDAO interface
public interface UserDAO extends BaseDAO {
//abstract methods for User
}
//4. UserDAOJdbcImpl.java class file
#Repository
public class UserDAOJdbcImpl extends BaseDAOJdbcImpl implements UserDAO
{
// implementations of above UserDAO abstract methods
}
And the webapp-servlet.xml Spring-MVC config file :-
.
.
<mvc:annotation-driven/>
<context:annotation-config/>
<context:component-scan base-package="springcrud"/>
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/pmsDS"/>
</bean>
<bean id="baseDAOJdbcImpl" class="springcrud.dao.BaseDAOJdbcImpl">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass">
<value>
org.springframework.web.servlet.view.tiles3.TilesView
</value>
</property>
</bean>
<bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles3.TilesConfigurer">
<property name="definitions">
<list>
<value>/WEB-INF/tiles.xml</value>
</list>
</property>
</bean>
.
.
I'm getting the following error :-
java.lang.IllegalArgumentException: 'dataSource' or 'jdbcTemplate' is required
The dataSource object is not being injected into DAO layer. Is the above DAO layer architecture valid or is it a problem with Spring configuration?

Spring mvc not able to read messages.properties file

I am trying to use custom validation error messages by using properties file. I have placed messages.properties file in web content/web-inf/ folder.
NonEmpty.batchDomain.batchName=Invalid message 2.
My applicationContext file is :
<context:component-scan base-package="com.coaching.controller" />
<!-- Enable annotation driven controllers, validation etc... -->
<mvc:annotation-driven />
<!-- Resolves view names to protected .jsp resources within the /WEB-INF/views
directory -->
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/views/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<mvc:default-servlet-handler />
<mvc:resources mapping="/resources/**" location="/resources/" />
<bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="/WEB-INF/messages" />
</bean>
And my controller is :
#RequestMapping(method = RequestMethod.POST)
public ModelAndView addBatch(
#Valid #ModelAttribute("batchDomain") BatchDomain batchDomain,
BindingResult result, HttpServletRequest request,
HttpServletResponse response) throws Exception {
try {
if (result.hasErrors()) {
ModelAndView modelAndView = new ModelAndView("newBatch");
return modelAndView;
}
}
BatchDomain is :
public class BatchDomain {
#NotNull
#NotEmpty
#Size(min = 1, max = 100)
private String batchName;
#Min(1)
#Max(1000)
private int strength;
}
As far as I have seen in google, I am following the correct approach. So, what can be the reason behind this issue?
You may try to put file "messages.properties" in /src/main/resource directory.

RestTemplate POST with JSon

once again iam looking a for help/guide from experts,
My problem is, i need to create Dynamic web site which calls to restfull server to get data, all the requests are POST and returns json object. Iam thinking of use of Spring RestTemplate to make calls to server. My Server works ok, meaning currently some android and Apple apps connects to same APIs and they work ok. But when i try to use RestTemplate to connect to server, it gives some errors
org.springframework.web.client.HttpClientErrorException: 400 Bad Request
this is my server,
#Controller
public class ABCController
{
#RequestMapping(method = RequestMethod.POST, value = "/user/authenticate")
public #ResponseBody LoginResponse login(#RequestParam("email") String email,#RequestParam("password") String password,#RequestParam("facebookId") String facebookId) {
LoginRequest request = new LoginRequest(email, password, facebookId);
UserBusiness userBusiness = UserBusinessImpl.getInstance();
return userBusiness.login(request);
}
}
And this is my spring configs of server,
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd">
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
<bean id="jsonViewResolver" class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
<bean id="viewResolver" class="org.springframework.web.servlet.view.BeanNameViewResolver" />
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="jsonConverter" />
</list>
</property>
</bean>
<bean id="jsonConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<property name="supportedMediaTypes" value="application/json" />
</bean>
<bean name="abcController" class="com.abc.def.controller.ABCController" />
<mvc:annotation-driven />
</beans>
This is how i try to call the server using RestTemplate,
<bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
<!-- <constructor-arg ref="httpClientFactory"/> -->
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<property name="objectMapper">
<ref bean="JacksonObjectMapper" />
</property>
</bean>
</list>
</property>
</bean>
<bean id="JacksonObjectMapper" class="org.codehaus.jackson.map.ObjectMapper" />
and this is how i use it (for testing)
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("root-context.xml");
RestTemplate twitter = applicationContext.getBean("restTemplate", RestTemplate.class);
MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
map.add("email", "x1#test.com");
map.add("password", "abc");
map.add("facebookId", null);
HttpEntity<LoginResponse> response= twitter.exchange("https://abc.com/Rest/api/user/authenticate", HttpMethod.POST, map, LoginResponse.class);
my login response class, and its sub classes,
LoginResponse
public class LoginResponse extends BaseResponse {
private LoginBase data;
with getters and setters
}
Login Base
public class LoginBase {
private String token;
private User user;
with getters and setters
}
User
public class User {
private Integer userId;
private String email;
private Integer status;
private String name;
with getters and setters
}
finally BaseResponse
public class BaseResponse {
protected String statusCode;
with getter and setter }
My questions are,
1. Why do i get this error when i call the server
INFO : org.springframework.beans.factory.support.DefaultListableBeanFactory - Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory#63de8f2d: defining beans [restTemplate,JacksonObjectMapper]; root of factory hierarchy
WARN : org.springframework.web.client.RestTemplate - POST request for "https://abc.com/Rest/api/user/authenticate" resulted in 400 (Bad Request); invoking error handler
Exception in thread "main" org.springframework.web.client.HttpClientErrorException: 400 Bad Request
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:90)
at org.springframework.web.client.RestTemplate.handleResponseError(RestTemplate.java:494)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:451)
2. how do i map json response to java LoginResponse
You might have to add the content-type and accept headers to your request.
Mapping the response to LoginResponse can be done directly like this
LoginResponse lResponse = response.getBody();
or If you are using restTemplate.postForObject(), the reponse will be in the form of LoginResponse

MappingJacksonJsonView return top-level json object

I converted to controller to use ContentNegotiatingViewResolver instead of MessageConverters to support multiple output types. With json, I am using MappingJacksonJsonView:
<bean
class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="order" value="1" />
<property name="mediaTypes">
<map>
<entry key="html" value="text/html"/>
<entry key="json" value="application/json" />
<entry key="xml" value="application/xml" />
</map>
</property>
<property name="defaultViews">
<list>
<bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
<bean class="org.springframework.web.servlet.view.xml.MarshallingView">
<constructor-arg>
<bean class="org.springframework.oxm.xstream.XStreamMarshaller" />
</constructor-arg>
</bean>
</list>
</property>
<property name="ignoreAcceptHeader" value="true" />
<property name="defaultContentType" value="application/json" />
</bean>
With the following controller logic:
#RequestMapping(value = "/id/{id}", method = RequestMethod.GET)
public ModelAndView getById(#PathVariable (value="id") String id) {
MyObject ret = doGetById(id);
ModelAndView modelAndView = new ModelAndView("common/single");
modelAndView.addObject("myObject", ret);
return modelAndView;
}
The json return when I access /id/1234.json is something like:
{
myObject: {
field1:"abc",
field2:"efg"
}
}
Is there a way for my to set myObject as the top level node for the result so it look like this instead:
{
field1:"abc",
field2:"efg"
}
What's happening is Spring MVC is taking the ModelAndView and serializing it to JSON. Since a ModelAndView just looks like a map, and in this case, you only have one entry in the map with a key name of myObject, that's what the JSON response looks at. In order to get just your object, you need to return just your object instead of a ModelAndView and let Jackson serialize your object to JSON.
Rather than returning a ModelAndView, return a MyObject and annotate the method with #ResponseBody, so your controller method becomes
#RequestMapping(value="/id/{id}", method=RequestMethod.GET, produces="application/json")
public #ResponeBody MyObject getById(#PathVariable (value="id") String id) {
return doGetById(id);
}
I faced same issue and following solution works for me.
<bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView">
<property name="prefixJson" value="true" />
</bean>
You should be able to remove the outer node by using MappingJacksonJsonView.setExtractValueFromSingleKeyModel(true):
Set whether to serialize models containing a single attribute as a map
or whether to extract the single value from the model and serialize it
directly.
The effect of setting this flag is similar to using
MappingJacksonHttpMessageConverter with an #ResponseBody
request-handling method.
For example:
private final MappingJacksonJsonView view = new MappingJacksonJsonView();
public MyController() {
view.setExtractValueFromSingleKeyModel(true);
}
#RequestMapping(value = "/id/{id}", method = RequestMethod.GET)
public ModelAndView getById(#PathVariable (value="id") String id) {
MyObject ret = doGetById(id);
ModelAndView modelAndView = new ModelAndView();
modelAndView.setView(this.view);
modelAndView.addObject("myObject", ret);
return modelAndView;
}
This should also work if you prefer to do it via configuration:
<bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView">
<property name="extractValueFromSingleKeyModel" value="true" />
</bean>

Resolve PageNotFound with spring MultiActionController

I am trying to use a MultiActionController in spring mvc, but I keep getting a 404 with the following message in the log
(org.springframework.web.servlet.PageNotFound)
No mapping found for HTTP request with
URI [/www.mysite.no/a/b/c] in
DispatcherServlet with name 'myServlet'
It looks like I'm following the book example, but it still doesn't work? Ideas, anyone?
Code samples: web.xml
<servlet-mapping>
<servlet-name>subscriptionServlet</servlet-name>
<url-pattern>/a/b/*</url-pattern>
</servlet-mapping>
Spring config: my-servlet.xml
<beans ...>
<bean id="myController" class="foo.bar.MyController">
<property name="methodNameResolver" ref="productMethodNameResolver"/>
</bean>
<bean id="productMethodNameResolver" class="org.springframework.web.servlet.mvc.multiaction.PropertiesMethodNameResolver">
<property name="mappings">
<value>
/*=view
</value>
</property>
</bean>
</beans>
The controller:
public class MyController extends MultiActionController {
Log logger = ...
#Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception{
logger.fatal("Never displayed in log");
return super.handleRequest(request, response);
}
public ModelAndView view(HttpServletRequest request, HttpServletResponse response) throws Exception {
logger.fatal("Never displayed in log");
return null;
}
I had included url mapping to methods within the controller, but lacked url mapping to the actual controller. The following must be added to the spring config
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<value>
/*=myController
</value>
</property>
</bean>

Resources