Spring mvc RestTemplate postForObject doesn't send parameter to REST API - spring

I have a REST API. I'm making a client.
I configured spring security to authentication by my rest service.
My REST API controller
#RequestMapping(value = "/login", method = RequestMethod.POST, headers="content-type=application/json")
public #ResponseBody
UserDetails loginUser(WebRequest request)
throws LoginOrPasswordException {
logger.info("login user");
logger.info(request);
String username = request.getParameter("username");
logger.info(username);
UserDetails uDetails = userRepository.login(username);
System.out.println(uDetails.getPassword());
return uDetails;
}
Application context of API
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc" 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-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<mvc:annotation-driven />
<context:component-scan base-package="com.zayats." />
<bean
class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<bean
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" />
</list>
</property>
</bean>
<!-- Http Json MessageConverter -->
<bean id="jsonConverter"
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="supportedMediaTypes" value="application/json" />
</bean>
<import resource="jdbc-config.xml" />
Next is client method with restTemplate
HashMap<String, String> params = new HashMap<String, String>();
params.put("username", username);
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<?> httpEntity = new HttpEntity<Object>(params, requestHeaders);
logger.info("Create map and doing request.");
UserDetails matchingUser = restTemplate.postForObject(
"http://localhost:8080/ApiFamilyShoplist/user/login", httpEntity,
UserDetails.class);
Rest Template config
<bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
<property name="messageConverters">
<list>
<bean id="jsonConverter"
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="supportedMediaTypes" value="application/json" />
</bean>
</list>
</property>
</bean>
When I call my API with postForObject in controller of API doesn't receive any parameters.
Please, give me some advice how to make it to send data to API.
Thanks.

You need to have another parameter in your method to accept the string parameter and annotate it with #RequestBody (inside the method signature):
#ResponseBody
#Consumes("text/plain")
public UserDetails loginUser(WebRequest request, #RequestBody String userName)
Also, if you're passing a string, I suggest to add a simple http string converter to the converters of the rest template and annotate the server method with #Consumes(text/plain). This way you'll get it as a simple string.

Related

Configure Gson in Spring before using GsonHttpMessageConverter

How to configure Gson before constructing a GsonHttpMessageConverter?
I need to use #Expose and specify Date format.
(New Method) Using Java Config
Extend WebMvcConfigurerAdapter or if you need more control use WebMvcConfigurationSupport.
#Configuration
#EnableWebMvc
public class WebMvcConfig extends WebMvcConfigurerAdapter {
#Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(createGsonHttpMessageConverter());
super.configureMessageConverters(converters);
}
private GsonHttpMessageConverter createGsonHttpMessageConverter() {
Gson gson = new GsonBuilder()
.excludeFieldsWithoutExposeAnnotation()
.setDateFormat("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'SSS'Z'")
.create();
GsonHttpMessageConverter gsonConverter = new GsonHttpMessageConverter();
gsonConverter.setGson(gson);
return gsonConverter;
}
}
You can read more on how to customize provided configuration.
(Old Method) Using XML configuration
In DispatcherServlet context:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="gsonBuilder" class="com.google.gson.GsonBuilder">
<property name="dateFormat" value="yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'SSS'Z'" />
</bean>
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject" ref="gsonBuilder" />
<property name="targetMethod" value="excludeFieldsWithoutExposeAnnotation" />
</bean>
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.json.GsonHttpMessageConverter">
<property name="gson">
<bean class="com.google.gson.Gson" factory-bean="gsonBuilder" factory-method="create" />
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
</beans>

Adding Authentication Token to Spring Data Neo4j Rest

How do I add the authentication token created by Neo4j Server to Spring Neo4j Rest configuration
context.xml
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<import resource="spring-data-context.xml" />
<bean id="graphDatabaseService"
class="org.springframework.data.neo4j.rest.SpringRestGraphDatabase">
<constructor-arg index="0" value="http://localhost:7474/db/data" />
</bean>
</beans>
As per the SpringRestGraphDatabase class, there are two more parameters which can be passed into Constructor which are username and password.
Here is how you should configure it.
<bean id="graphDatabaseService" class="org.springframework.data.neo4j.rest.SpringRestGraphDatabase">
<constructor-arg value="http://localhost:7474/db/data"/>
<constructor-arg name="user" value="neo4j"/>
<constructor-arg name="password" value="******"/>
</bean>
Ended using Jersey Client's HttpBasicAuthFilter
Your parameters should be something like:
public static final String DATABASE_ENDPOINT = "http://localhost:7474/db/data";
public static final String DATABASE_USERNAME = "neo4j";
public static final String DATABASE_PASSWORD = "3c0a0a6ea1sdsdsdsdsdsdsdsdf2a94d";
private String callRest(String query) {
final String cypherUrl = ENDPOINT + "/cypher";
Client c = Client.create();
c.addFilter(new HTTPBasicAuthFilter(USERNAME, PASSWORD));
WebResource resource = c.resource(cypherUrl);
String request = "{\"query\":\"" + query + "\"}";
ClientResponse response = resource.accept(MediaType.APPLICATION_JSON)
.type(MediaType.APPLICATION_JSON).entity(request)
.post(ClientResponse.class);
String object = response.getEntity(String.class);
response.close();
return object;
}
Latest Jersey client can be found by adding this to your mvn pom if its not already in your dependency tree.
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-client</artifactId>
<version>1.18.3</version>
</dependency>

Spring controller not accepting application/json

When I am passing application/json parameters from Chrome Rest Client,I am getting 400 bad request error.
When I add required=false for #RequestParam, the request is accepted by Controller but the values is Null.
#RequestMapping(value = "/add",
method = RequestMethod.POST,
consumes="application/json",
produces="application/json")
public #ResponseBody String add(
#RequestParam(value="surveyName") String surveyName,
#RequestParam(value="surveyDesc") String surveyDesc,
ModelMap model) throws Exception
{
System.out.println("request parameters in /add/syrvey surveyName= "+surveyName);
}
My JSON request is as below and Content-Type is "aplication/json"
{"surveyName"="sd", "surveyDesc":"sd"}
I tried using headers="Accept=application/json",but it didn't help much.
My dispatcher-servlet is
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=">
<context:annotation-config />
<context:component-scan base-package="com.survey.controller" />
<context:component-scan base-package="com.survey.service" />
<context:component-scan base-package="com.survey.dao" />
<context:component-scan base-package="com.survey.entity" />
<context:component-scan base-package="com.survey.constants" />
<mvc:annotation-driven />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
<bean id="jacksonMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" />
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="jacksonMessageConverter" />
</list>
</property>
</bean>
</beans>
My pom.xml is
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.12</version>
</dependency>
Any help greatly appreciated
In your situation you can use a Map:
public #ResponseBody String add(#RequestBody Map<String, String> input) throws Exception
and then iterate over it in order to find your parameters, or you can use a Pojo
public class Pojo {
private String surveyName;
private String surveyDesc;
...
}
public #ResponseBody String add(#RequestBody Pojo pojo) throws Exception
Hope this can be useful!
#RequestParam can not be used to load parts of a complex json object. It is designed for selecting request parameter, but not to select something within a (single) request parameter.
You need to use #RequestBody and a container object
public class MyContainer {
private String surveyName;
private String surveyDesc;
...
}
public #ResponseBody String add(#RequestBody Container container){...}
Or you can implement a solution described by Biju Kunjummen in his answer to a similar question. The idea is to implement your own HandlerMethodArgumentResolver that is triggered by an parameter annotation which take a JsonPath expression argument
public #ResponseBody String add(
#JsonArg("/surveyName") String surveyName,
#JsonArg("/surveyDesc") String surveyDesc){...}
Have a look at Passing multiple variables in #RequestBody to a Spring MVC controller using Ajax for the implementation details.
If you like this answer, then please also upvote Biju Kunjummen answer, because it is his idea. I only goggled a bit because it is an interesting question.
also add those two library in lib or add maven for this.
jackson-jaxrs-1.6.1.jar
jackson-mapper-asl-1.9.9.jar

Injection of the sessionFactory not working

I'm new with Spring and I want to inject the sessionFactory and its not working at all. I'm starting a web server Jetty and then I load the context. After i start a GWT web application, I make a call on the server side and I try to get some info but I get a null pointer. There is no error at all so it make it difficult to know where the problem is. I know its suppose to work because I saw it working on a project I worked on some times ago. Any help will be appreciate. (Sorry for my possibly bad english)
Here is the context.xml :
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema
/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema
/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema
/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema
/security/spring-security-3.0.xsd">
<!-- Standard spring initialization -->
<context:component-scan base-package="com.test">
</context:component-scan>
<tx:annotation-driven transaction-manager="txManager"/>
<!-- Connection to the database-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-
method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/test" />
<property name="username" value="root" />
<property name="password" value="123456789" />
</bean>
<!-- Hibernate session factory-->
<bean id="jpaSessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="com.domain"/>
<property name="namingStrategy" >
<bean class="org.hibernate.cfg.ImprovedNamingStrategy" />
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
<prop key="show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
</bean>
<!-- Hibernate session factory -->
<bean id="txManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="jpaSessionFactory" />
</bean>
</beans>
Here is the main :
public static void main(String[] args) {
ContextHandlerCollection contexts = new ContextHandlerCollection();
contexts.setHandlers(new Handler[]
{ new AppContextBuilder().buildWebAppContext()});
final JettyServer jettyServer = new JettyServer();
jettyServer.setHandler(contexts);
Runnable runner = new Runnable() {
#Override
public void run() {
new ServerRunner(jettyServer);
}
};
EventQueue.invokeLater(runner);
new ClassPathXmlApplicationContext("context.xml");
}
Here is the class Test where I want the injection :
#Component("test")
public class TEST{
#Resource(name="jpaSessionFactory")
private SessionFactory sessionFactory;
#SuppressWarnings("unchecked")
#Transactional(readOnly = true)
public List<Personne> getPersonnes() {
Session s = sessionFactory.getCurrentSession();
Query query = s.createQuery("from Person");
return query.list();
}
}
Here is the server side from the application (not shown completely)
/*** The server side implementation of the RPC service.
*/
#SuppressWarnings("serial")
public class GreetingServiceImpl extends RemoteServiceServlet implements
GreetingService {
#Resource
private TEST t;
public String greetServer(String input) throws IllegalArgumentException {
// Verify that the input is valid.
if (!FieldVerifier.isValidName(input)) {
// If the input is not valid, throw an IllegalArgumentException
back to
// the client.
throw new IllegalArgumentException(
"Name must be at least 4 characters long");
}
t.getPersons(); // NULL pointer here
.........................
The MySQL tables are created like it should, so all the scanning seems to work.
Thanks
Bob
This is because the GreetingServiceImpl class is not created by spring - it is servlet that is initialized by the container directly. Follow the instructions in this article to fix the issue. I have copied the relevant code from the article.
#Override
public void init() throws ServletException {
super.init();
final WebApplicationContext ctx =
WebApplicationContextUtils.getWebApplicationContext(getServletContext());
if (ctx == null) {
throw new IllegalStateException("No Spring web application context found");
}
ctx.getAutowireCapableBeanFactory().autowireBeanProperties(this,
AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);
}

Spring MVC Page is not rendering the success page using simpleformcontroller

Iam wrote simple spring mvc apps.But I unable to redirect one page to another page. I mentioned code snippet below
Claims-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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 id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props><prop key="/loginpage.htm">loginFormController</prop></props>
</property>
</bean>
<bean id="loginFormController" class="com.aims.controller.LoginFormController">
<property name="sessionForm"><value>true</value></property>
<property name="commandName"><value>LoginFormCommand</value></property>
<property name="commandClass"><value>com.aims.commands.LoginFormCommand</value></property>
<property name="validator"><ref bean="loginformValidator"/></property>
<property name="formView"><value>loginpage</value></property>
<property name="successView"><value>body</value></property>
</bean>
<bean id="loginformValidator" class="com.aims.validator.LoginFormValidator"/>
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass"><value>org.springframework.web.servlet.view.JstlView</value></property>
<property name="suffix"><value>.jsp</value></property>
</bean>
</beans>
Controller:
public class LoginFormController extends SimpleFormController {
public ModelAndView onSubmit(Object command, BindException bindException) throws Exception {
System.out.println("LoginFormController:onSubmit============");
LoginFormCommand loginform = (LoginFormCommand) command;
System.out.println("username" + loginform.getUsername() + "Password"
+ loginform.getPassword());
return new ModelAndView(new RedirectView("/WEB-INF/view/jsp/"
+ getSuccessView()));
}}
I have two jsp one is
Webroot>loginpage.jsp
view->jsp>body.jsp
When the browser opens its automatically called loginpage.jsp(web.xml>welecome-file) and after success iam trying to call view->jsp>body.jsp.But it doesn't move to body.jsp.Please need help.
With a redirect view, you must specify the actual URL of the target, not a path to an internal jsp. Instead of rendering a jsp, Spring MVC will redirect the user to this URL.
Example: new ModelAndView(new RedirectView("/example/helloworld.html")).
Of course, the target has to exist.

Resources