I have a simple controller, which should return JSON, but is failing to do so. The JSON library is Jackson, configured as a maven dependency. When I make a request using postman, against this url path, I am receiving a 404 error. When I attempt to inspect the JSON Returned, I see "Malformed JSON: Unexpected '<'".
Could someone suggest what it is I am missing / failing to understand? Thank you
#RestController
#RequestMapping("/World/")
public class RestfulController {
#RequestMapping(value = "/Country/", method = RequestMethod.GET, produces="application/json")
public ResponseEntity<Country> findAllCountrys(){
Country c = new Country(1, "Ethiopia", "Addis Abba", "94 Million");
return new ResponseEntity<Country>(c, HttpStatus.OK);
}
}
spring application context
<beans xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
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
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.restfulapp.controller"/>
<mvc:annotation-driven/>
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="mediaTypes">
<map>
<entry key="json" value="application/json" />
</map>
</property>
</bean>
You should try this:
#RestController
#RequestMapping("/World")
public class RestfulController {
#RequestMapping(value = "/Country", method = RequestMethod.GET)
public Country findAllCountrys(){
Country c = new Country(1, "Ethiopia", "Addis Abba", "94 Million");
return c;
}
}
The request url: http://yourhost/World/Country
This should return a json of Country
Related
I have a spring MVC (4.1.6) app, using Hibernate ORM (5.3.7) on top of a MySQL 8 Database.
I have a view with a form that should create a row in the DB when it is submitted, but it does not. I can tell the information gets to my #Service bean and DAO #Repository bean. I can also successfully query data from the DB and display it on a view, if I update the DB directly through SQL.
I have read a number of posts and tried to reconfigure my application context and servlet context XMLs with no luck. Can anyone tell me where I am going wrong?
Below are some snippets.
Web_XML
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/applicationContext-dao.xml
/WEB-INF/spring/applicationContext-security.xml
</param-value>
</context-param>
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/applicationContext-web.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
applicationContext-web.xml
<context:component-scan base-package="edu.neu.snowfinder">
<context:include-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
</context:component-scan>
<interceptors>
<beans:bean class= "org.springframework.orm.hibernate4.support.OpenSessionInViewInterceptor">
<beans:property name="sessionFactory" ref="sessionFactory"/>
</beans:bean>
</interceptors>
applicationContext-dao.xml
<bean id="sessionFactory" class = "org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name = "dataSource" ref = "dataSource"/>
<property name = "configLocation">
<value> classpath:hibernate.cfg.xml</value>
</property>
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id = "transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref = "sessionFactory"/>
<property name="dataSource" ref = "dataSource"/>
</bean>
UserServiceImpl
#Service
public class UserServiceImpl implements UserService {
#Autowired
#Qualifier("userHibernateDAO")
private UserDAO userDAO;
#Override
#Transactional
public void createUser(User user) {
System.out.println("Does the Sevice have the user?"+user.getFirstname());
userDAO.createUser(user);
}
#Override
#Transactional
public Collection<User> listUsers() {
return userDAO.listUsers();
}
}
UserHibernateDAO
#Repository
public class UserHibernateDAO implements UserDAO {
#Autowired
private SessionFactory sessionFactory;
#Override
public void createUser(User user) {
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
System.out.println("Does the DAO have the user?"+user.getFirstname());
System.out.println("Does the DAO have a session?"+sessionFactory.getCurrentSession().toString());
Serializable id = sessionFactory.getCurrentSession().save(user);
session.getTransaction().commit();
System.out.println("Whats the saved User's ID??"+id.toString());
}
hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration SYSTEM
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name = "hibernate.dialect">org.hibernate.dialect.MySQL8Dialect</property>
<property name = "hibernate.showsql">true</property>
<property name = "hibernate.formatsql">true</property>
<property name = "hibernate.hbm2ddl.auto">create</property>
<mapping class = "edu.neu.snowfinder.model.User"/>
</session-factory>
</hibernate-configuration>
i try to send json object from angular frontend to spring mvc backend without success. This is my config and what i have tried :
config :
web.xml :
<servlet>
<servlet-name>rest</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:/META-INF/jdu/contexts/rest-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>rest</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
rest-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.xsd">
<bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView">
<!-- prevent JSON Hijacking -->
<property name="prefixJson" value="true"/>
</bean>
</beans>
applicationContext:
<!-- Configures the annotation-driven Spring MVC Controller programming model.
Note that, with Spring 3.0, this tag works in Servlet MVC only! -->
<mvc:annotation-driven>
<mvc:message-converters>
<!-- Use the HibernateAware mapper instead of the default -->
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean class="com.mc.jdu.utils.HibernateAwareObjectMapper"/>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
pom.xml with jackson-version = 2.6.3:
<!-- Data Mapper package is a high-performance data binding package built
on Jackson JSON processor -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-hibernate4</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency><!-- jackson -->
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.13</version>
</dependency>
my controller :
#RequestMapping(value="/create", method=RequestMethod.POST)
#ResponseBody
public StatusResponse create(EventsDTO eventsDTO) throws TechnicalException {
return service.create(eventsDTO);
}
EventDTO :
public class EventsDTO implements BeanInterface{
private String textColor;
private String color;
private List<CallendarDTO> events = new ArrayList<CallendarDTO>();
public EventsDTO(){
}
// getters and setters
CallendarDTO :
public class CallendarDTO {
private String title;
private String libelle;
private String date;
private String start;
private String end;
private String duree;
private boolean allDay;
private boolean stick;
Angular :
var _queryPost = function(url, data, defData) {
$http({
headers:{'Content-Type':'application/json'},
method: 'POST',
url: url,
params: data
})
.success( function(data, status, headers, config) {
defData.$resolve(data);
$log.info(data);
})
. error(function(data, status, headers, config) {
$log.warn('*** DataProvider - query - error - status:' + status);
401===status?$location.path('/signIn'):$location.path('/error' + status);
defData.$reject(data);
});
return defData;
};
And the data :
$scope.eventsDTO = [];
$scope.eventsDTO.color = "green ";
$scope.eventsDTO.texColor="";
//$scope.eventsDTO.events=[];
$scope.eventsDTO.events= [
{
"title":"1",
"date":"2013-10-04",
"libelle":"lib 1",
"start":"08:30",
"end":"10:30",
"duree":"02:00",
"allDay":false,
"stick":true
},
{
"title":"2",
"date":"2013-10-04",
"libelle":"lib 2",
"start":"08:30",
"end":"10:30",
"duree":"02:00",
"allDay":false,
"stick":true
}
];
OK. if i try like this i get : "the server responded with a status of 400 (Bad Request)"
If the events list is empty, it works....but of course i need this list
So i red this post : Spring MVC : post request and json object with array : bad request
and i have tried to add #RequestBody on the controller like this :
#RequestMapping(value="/create", method=RequestMethod.POST)
#ResponseBody
public StatusResponse create(#RequestBody EventsDTO eventsDTO) throws TechnicalException {
return service.create(eventsDTO);
}
but now i get : "the server responded with a status of 415 (Unsupported Media Type)"
In fact, the app works when i pass object without List inside. But if there is a List (like EventsDTO with its CallendarDTO List), it doesn't work.
The error 415 by adding #RequestBody make me think that my Jackson config is wrong...but where ?
I have tried to change apllicationContext.xml configuration with what i have found ont the web, for exemple, by adding :
<bean id="jacksonMessageConverter"
class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>
<bean
class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="jacksonMessageConverter" />
</list>
</property>
</bean>
But i don't understand exactly how does it work..
How can i pass my EventsDTO ?
Using WSO2 ESB, I'm trying to send an AMQP message to the WSO2 message broker. This AMQP message should have JSON content type.
I expose a Proxy service in WSO2 ESB that gets the message, transforms it to JSON and sends it to the message broker. The proxy service configuration looks like :
<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse" name="json_sample" transports="http" statistics="disable" trace="disable" startOnLoad="true">
<target>
<inSequence>
<property name="OUT_ONLY" value="true" scope="default" type="STRING"/>
<property name="FORCE_SC_ACCEPTED" value="true" scope="axis2"/>
<property name="messageType" value="application/json" scope="axis2" type="STRING"/>
<log level="full"/>
<header name="To"
value="jms:/sample-queue?transport.jms.ConnectionFactoryJNDIName=sampleConnectionFactory&java.naming.factory.initial=org.wso2.andes.jndi.PropertiesFileInitialContextFactory&java.naming.provider.url=repository/conf/jndi.properties&transport.jms.DestinationType=queue"/>
<send/>
</inSequence>
</target>
<publishWSDL>
<definitions name="JsonSample" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://www.examples.com/wsdl/JsonSample.wsdl" targetNamespace="http://www.examples.com/wsdl/JsonSample.wsdl">
<message name="JsonSampleRequest">
<part name="prop1" type="xsd:string"/>
<part name="prop2" type="xsd:string"/>
</message>
<portType name="JsonSample_PortType">
<operation name="jsonObject">
<input message="tns:JsonSampleRequest"/>
</operation>
</portType>
<binding name="JsonSample_Binding" type="tns:JsonSample_PortType">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="jsonObject">
<soap:operation soapAction="jsonObject"/>
<input>
<soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:examples:jsonsample" use="encoded"/>
</input>
</operation>
</binding>
<service name="JsonSample_Service">
<port binding="tns:JsonSample_Binding" name="JsonSample_Port">
<soap:address location="http://www.examples.com/JsonSample/"/>
</port>
</service>
</definitions>
</publishWSDL>
<description/>
</proxy>
This proxy service works well, transforming the message to JSON, but do not set AMQP message content type to JSON. The message is considered as text.
When I try to inject an AMQP message in the message broker programmatically, using this code, I really have a message with JSON content type :
import java.util.Properties;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueSession;
import javax.naming.Context;
import javax.naming.InitialContext;
import org.wso2.andes.client.message.JMSTextMessage;
public class StackOverflowSample {
private static final String QPID_ICF = "org.wso2.andes.jndi.PropertiesFileInitialContextFactory";
private static final String CF_NAME_PREFIX = "connectionfactory.";
private static final String CF_NAME = "qpidConnectionfactory";
private static final String CARBON_CLIENT_ID = "carbon";
private static final String CARBON_VIRTUAL_HOST_NAME = "carbon";
private static final String host = "localhost";
private static final int port = 5675;
private static final String userName = "admin";
private static final String password = "admin";
private static final String queueName = "sample-queue";
public static void main(String[] args) throws Exception {
Properties properties = new Properties();
properties.put(Context.INITIAL_CONTEXT_FACTORY, QPID_ICF);
properties.put(CF_NAME_PREFIX + CF_NAME, getTCPConnectionURL(userName, password));
InitialContext ctx = new InitialContext(properties);
// Lookup connection factory
QueueConnectionFactory connFactory = (QueueConnectionFactory) ctx.lookup(CF_NAME);
QueueConnection queueConnection = connFactory.createQueueConnection();
queueConnection.start();
QueueSession queueSession = queueConnection.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE);
// Send message
Queue queue = queueSession.createQueue(queueName);
// create the message to send
JMSTextMessage textMessage = (JMSTextMessage) queueSession
.createTextMessage("{\"prop1\":\"value1\",\"prop2\":\"value2\"}");
textMessage.setContentType("application/json");
javax.jms.QueueSender queueSender = queueSession.createSender(queue);
queueSender.send(textMessage);
queueSender.close();
queueSession.close();
queueConnection.close();
}
private static String getTCPConnectionURL(String username, String password) {
// amqp://{username}:{password}#carbon/carbon?brokerlist='tcp://{hostname}:{port}'
return new StringBuffer().append("amqp://").append(username).append(":").append(password).append("#")
.append(CARBON_CLIENT_ID).append("/").append(CARBON_VIRTUAL_HOST_NAME).append("?brokerlist='tcp://")
.append(host).append(":").append(port).append("'").toString();
}
}
Changing textMessage.setContentType("application/json"); to textMessage.setContentType("text/plain"); gives me the same result as using the ESB.
So the question is : how can I configure the ESB to set the AMQP message content type as JSON ?
Thanks
<property name="messageType" value="application/json" scope="axis2" type="STRING"/>
is used to choose message formatter class.
You could have a try with :
<property name="ContentType"
value="application/json"
scope="axis2"
type="STRING"/>
I have some huge trouble receiving JSON from my simple Spring Controller although I checked against many other tutorials and even the official spring blog and could not find any difference, so please help me.
So my dependencies in my project are:
spring-context 3.2.2 RELEASE
spring-web 3.2.2 RELEASE
spring-webmvc 3.2.2 RELEASE
spring-test 3.2.2 RELEASE
junit 4.10
servlet-api 2.5
atmosphere-runtime 1.1.0 RC4
logback-classic 1.0.13
libthrift 0.9.0
jackson-mapper-asl 1.9.12
jackson-core-asl 1.9.12
My Controller is very simple and just generates a random UUID and returns it. It looks as follows:
#Controller
public class SimpleController {
#RequestMapping(value="/new", method=RequestMethod.GET)
public #ResponseBody SimpleResponse new() throws JsonGenerationException, JsonMappingException, IOException {
SimpleResponse sr = new SimpleResponse();
sr.setId(UUID.randomUUID().toString());
return sr;
}
}
The model is just a simple POJO like
public class SimpleResponse {
private String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
Configuration is done like this
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5" xmlns="http://java.sun.com/xml/ns/javaee">
<display-name>SimpleTest</display-name>
<servlet>
<servlet-name>app</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>app</servlet-name>
<url-pattern>/app/*</url-pattern>
</servlet-mapping>
</web-app>
and
<?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"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<mvc:annotation-driven />
<context:component-scan base-package="de.tum.ibis.wsc" />
</beans>
So thats the server side. On the client side I have a html page with just one line of jQuery code
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<script src="http://code.jquery.com/jquery.js"></script>
<script>
$(document).ready(function() {
$.getJSON("http://localhost:8080/Frontend/app/new", function(data) { console.log("it works"); });
});
</script>
</head>
<body>
</body>
</html>
Now according to everything I have read this should work but it does not for me. If I call localhost:8080/Frontend/app/new directly in my browser I get something like this: {"id":"b46b8d67-5614-44ed-90ef-d2da14d260f6"} and Firebug tells me that the response header from the server is
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Server: Jetty(7.6.5.v20120716)
so content-type should be fine. Well if I now run the jquery ajax call I get the error "JSON.parse: unexpected end of data " in jquery.js and I have no cloue why. I hope anybody can help me with that. Thanks!
------ Update ------
Firebug: jQuery error
Firebug: All I get
Firebug: This is what I get if a access the url directly
Try configuring ContentNegotiationManagerFactoryBean in Spring XML config, see Spring docs
Set favorPathExtension to false and update method's #RequestMapping like so
#RequestMapping(value="/new", method=RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
In your AJAX request, you're using
http://localhost:8080/Frontend/app/new
And your servlet declares URL "/new", you should use "/app/new" instead.
#RequestMapping(value="/app/new", method=RequestMethod.GET)
I would know how works the configuration about Spring MVC rest services that returns JSON.
I have configurated the applicationContenxt.xml in this way:
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"/>
</list>
</property>
</bean>
<bean id="contentNegotiatingViewResolver" class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="mediaTypes">
<map>
<entry key="json" value="application/json"/>
</map>
</property>
<property name="defaultViews">
<list>
<bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView"/>
</list>
</property>
</bean>
<bean class="com.MyController"></bean>
And this is the code of my controller:
#Controller(value="MyController")
public class MyController {
#RequestMapping(value="/getValue", method=RequestMethod.GET)
public ModelAndView getValue() {
Map model = new HashMap();
model.put("asasa", "bbbbb");
model.put("cccc", "ddddd");
return new ModelAndView("jsonView",model);
}
}
I'm missing something about xml configuration or Java code? I have always error 404 while trying to invoke this resource: http://localhost:8080/fss/MyController/getValue
Just do:
#Controller
public class HelloController {
#RequestMapping(value="/hello", method=RequestMethod.GET)
public #ResponseBody String hello(#RequestParam String name) {
return "Hi " + name;
}
}
Change the return type to an object and include jackson in the classpath for an object response.
The request need to have a application/json header for the controller to return json.
Check out http://blog.springsource.com/2010/01/25/ajax-simplifications-in-spring-3-0/
And don't forget to add jackson converter to Spring context file.
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>
</mvc:message-converters>
</mvc:annotation-driven>
By the way - if your method accepts JSON, then use #RequestBody annotation with incoming data type:
#RequestMapping
public #ResponseBody OutgoingClass getJsonByJson(#RequestBody IncomingClass data) {...}
You can find nice examples of JSON and Spring MVC and more https://sites.google.com/site/upida4j/example