Can not send JSON using POST request and Jackson - java

This is my entity class:
#Entity
#Table(name = "menuitem")
public class MenuItem {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY )
#Column(name = "id")
private Integer id;
#Column(name = "title")
private String title;
#Column(name = "eng_title")
private String engTitle;
#Column(name = "price")
private double price;
#Column(name = "description")
private String description;
#Column(name = "consist_of")
private String consistOf;
#Column(name = "volume_value")
private double volumeValue;
#Column(name = "volume_title")
private String volumeTitle;
#ManyToOne
#JoinColumn(name = "category_id",insertable = false, updatable = false)
private Category category;
#Column(name = "category_id")
private int categoryId;
public MenuItem() {
}
public MenuItem(JSONObject jsonObject) {
if (!jsonObject.isNull("id")) {
this.id = jsonObject.getInt("id");
}
if (!jsonObject.isNull("title")) {
this.title = jsonObject.getString("title");
}
if (!jsonObject.isNull("engTitle")) {
this.engTitle = jsonObject.getString("engTitle");
}
if (!jsonObject.isNull("price")) {
this.price = jsonObject.getDouble("price");
}
if (!jsonObject.isNull("description")) {
this.description = jsonObject.getString("description");
}
if (!jsonObject.isNull("consistOf")) {
this.consistOf = jsonObject.getString("consistOf");
}
if (!jsonObject.isNull("volumeValue")) {
this.volumeValue = jsonObject.getDouble("volumeValue");
}
if (!jsonObject.isNull("volumeTitle")) {
this.volumeTitle = jsonObject.getString("volumeTitle");
}
}
public MenuItem(Integer id, String title, String engTitle, double price,
String description, String consistOf, double volumeValue,
String volumeTitle) {
super();
this.id = id;
this.title = title;
this.engTitle = engTitle;
this.price = price;
this.description = description;
this.consistOf = consistOf;
this.volumeValue = volumeValue;
this.volumeTitle = volumeTitle;
}
#Override
public String toString() {
return "MenuItem [id=" + id + ", title=" + title + ", engTitle="
+ engTitle + ", price=" + price + ", description="
+ description + ", consistOf=" + consistOf + ", volumeValue="
+ volumeValue + ", volumeTitle=" + volumeTitle + ", categoryId=" + categoryId + "]";
}
public String getEngTitle() {
return engTitle;
}
public void setEngTitle(String engTitle) {
this.engTitle = engTitle;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getConsistOf() {
return consistOf;
}
public void setConsistOf(String consistOf) {
this.consistOf = consistOf;
}
public double getVolumeValue() {
return volumeValue;
}
public void setVolumeValue(double volumeValue) {
this.volumeValue = volumeValue;
}
public String getVolumeTitle() {
return volumeTitle;
}
public void setVolumeTitle(String volumeTitle) {
this.volumeTitle = volumeTitle;
}
#JsonBackReference
#JsonIgnore
public Category getCategory() {
return category;
}
public void setCategory(Category category) {
this.category = category;
}
public void setCategoryId(int categoryId) {
this.categoryId = categoryId;
}
}
This is my root context:
<beans:bean
class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<beans:property name="messageConverters">
<beans:array>
<beans:bean
class="org.springframework.http.converter.StringHttpMessageConverter">
<beans:property name="supportedMediaTypes" value="text/plain;charset=UTF-8" />
</beans:bean>
</beans:array>
</beans:property>
</beans:bean>
<!-- Resolves views selected for rendering by #Controllers to .jsp resources
in the /WEB-INF/views directory -->
<beans:bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<!-- Configure to plugin JSON as request and response in method handler -->
<beans:bean
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<beans:property name="messageConverters">
<beans:list>
<beans:ref bean="jsonMessageConverter" />
</beans:list>
</beans:property>
</beans:bean>
<!-- Configure bean to convert JSON to POJO and vice versa -->
<beans:bean id="jsonMessageConverter"
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
</beans:bean>
<mvc:interceptors>
<beans:bean class="ru.tenet.cafe.interceptor.LoginInterceptor" />
</mvc:interceptors>
<context:component-scan base-package="ru.tenet.cafe" />
<mvc:annotation-driven />
<tx:annotation-driven transaction-manager="transactionManager" />
<beans:bean id="dataSourceMain" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<beans:property name="driverClass" value="org.postgresql.Driver" />
<beans:property name="jdbcUrl"
value="jdbc:postgresql://192.168.101.158:5432/cafe" />
<beans:property name="user" value="postgres" />
<beans:property name="password" value="123" />
<beans:property name="minPoolSize" value="5" />
<beans:property name="maxPoolSize" value="8" />
<beans:property name="preferredTestQuery" value="SELECT 1" />
<beans:property name="acquireIncrement" value="1" />
<beans:property name="idleConnectionTestPeriod" value="100" />
<beans:property name="maxStatements" value="0" />
<beans:property name="checkoutTimeout" value="60000" />
</beans:bean>
<beans:bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<beans:property name="dataSource" ref="dataSourceMain" />
<beans:property name="configLocation">
<beans:value>/WEB-INF/db/hibernate.cfg.xml</beans:value>
</beans:property>
<beans:property name="hibernateProperties">
<beans:props>
<beans:prop key="hibernate.connection.characterEncoding">UTF-8</beans:prop>
<beans:prop key="hibernate.connection.charSet">UTF-8</beans:prop>
<beans:prop key="hibernate.connection.useUnicode">true</beans:prop>
<beans:prop key="hibernate.show_sql">false</beans:prop>
</beans:props>
</beans:property>
</beans:bean>
<beans:bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<beans:property name="sessionFactory" ref="sessionFactory" />
</beans:bean>
This is my controller:
#RequestMapping(value = "", method = RequestMethod.POST)
public ResponseEntity<String> create(
#RequestBody MenuItem menuItem) {
menuService.create(menuItem);
return new ResponseEntity<String>(HttpStatus.OK);
}
But if I send POST request with the following body
{
"title":"Пепперони",
"engTitle":"Pepperoni",
"price":300,
"description":"Сами лючщи пица слющи. Тольки щто привезли дарагой.",
"consistOf":"E666, стальная стружка, вода (без ГМО)",
"volumeValue":500,
"volumeTitle":"г",
"categoryId":38
}
I will get:
415 The server refused this request because the request entity is in a
format not supported by the requested resource for the requested
method.
What the hell?

let's start with a little definition :
415 Unsupported Media Type
The request entity has a media type which
the server or resource does not support. For example, the client
uploads an image as image/svg+xml, but the server requires that images
use a different format.
Which can be solved by :
#RequestMapping(value = "", method = RequestMethod.POST, produces = "application/json; charset=UTF-8", consumes = "application/json; charset=UTF-8")
Explanation : Basically you need to specify what kind of data your endpoint is going to consume / produce. Don't forget when sending the request to specify the header
Content-Type: application/json

Your current controller must be replaced with the following code:
#RequestMapping(value = "", method = RequestMethod.POST)
public ResponseEntity<String> create() {
MenuItem menuItem = null;
menuService.create(menuItem); // Fill in the menuItem
// Now respond
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.setContentType(MediaType.APPLICATION_JSON);
return new ResponseEntity<String>(menuItem, responseHeaders, HttpStatus.OK);
}

Related

How to create automatic tables in spring application?

"HI
automatic tables are not creating in spring application and application didnt get any error."
DB:MYSQL
"dispatcher-servlet.xml"
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="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/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
<annotation-driven />
<!-- Getting Database properties -->
<context:property-placeholder location="classpath:database.properties" />
<!-- Specifying the Resource location to load JS, CSS, Images etc -->
<resources mapping="/resources/**" location="/resources/" />
<!-- View Resolver -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/jsp/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<!-- DataSource -->
<beans:bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<beans:property name="driverClassName" value="${database.driver}" />
<beans:property name="url" value="${database.url}" />
<beans:property name="username" value="${database.username}" />
<beans:property name="password" value="${database.password}" />
</beans:bean>
<!-- Hibernate 4 SessionFactory Bean definition -->
<beans:bean id="hibernate4AnnotatedSessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<beans:property name="dataSource" ref="dataSource" />
<beans:property name="annotatedClasses">
<beans:list>
<beans:value>com.msebbz.beans.Calendar</beans:value>
</beans:list>
</beans:property>
<beans:property name="hibernateProperties">
<beans:props>
<beans:prop key="hibernate.dialect">${hibernate.dialect}</beans:prop>
<beans:prop key="hibernate.show_sql">${hibernate.show_sql}</beans:prop>
<beans:prop key="hibernate.format_sql">${hibernate.format_sql}</beans:prop>
<beans:prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl}</beans:prop>
</beans:props>
</beans:property>
</beans:bean>
<!-- Specifying base package of the Components like Controller, Service, DAO -->
<context:component-scan base-package="com.msebbz.*" />
<!-- Transaction -->
<beans:bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<beans:property name="sessionFactory" ref="hibernate4AnnotatedSessionFactory" />
</beans:bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<beans:bean id="Calendar" class="com.msebbz.beans.Calendar"/>
</beans:beans>
database.properties
#Database related properties
database.driver = com.mysql.jdbc.Driver
database.url = jdbc:mysql://localhost:3306/#######
database.username = #######
database.password = #######
#Hibernate related properties
hibernate.dialect = org.hibernate.dialect.MySQLDialect
hibernate.show_sql = true
hibernate.format_sql = true
hibernate.hbm2ddl = update
"Bean class"
package com.msebbz.beans;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name="calendar")
public class Calendar {
#Id
private String calendarId;
private String calendarName;
private String creationDate;
private String fromDate;
private String toDate;
private String status="Active";
private String calendarYear;
private String compOffExp;
private String holidays;
private String weekOff;
public String getCalendarId() {
return calendarId;
}
public void setCalendarId(String calendarId) {
this.calendarId = calendarId;
}
public String getCalendarName() {
return calendarName;
}
public void setCalendarName(String calendarName) {
this.calendarName = calendarName;
}
public String getCreationDate() {
return creationDate;
}
public void setCreationDate(String creationDate) {
this.creationDate = creationDate;
}
public String getFromDate() {
return fromDate;
}
public void setFromDate(String fromDate) {
this.fromDate = fromDate;
}
public String getToDate() {
return toDate;
}
public void setToDate(String toDate) {
this.toDate = toDate;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getCalendarYear() {
return calendarYear;
}
public void setCalendarYear(String calendarYear) {
this.calendarYear = calendarYear;
}
public String getCompOffExp() {
return compOffExp;
}
public void setCompOffExp(String compOffExp) {
this.compOffExp = compOffExp;
}
public String getHolidays() {
return holidays;
}
public void setHolidays(String holidays) {
this.holidays = holidays;
}
public String getWeekOff() {
return weekOff;
}
public void setWeekOff(String weekOff) {
this.weekOff = weekOff;
}
}
"Thanks in advance :)"
automatic tables are not creating in spring application and application didnt get any error."
automatic tables are not creating in spring application and application didnt get any error."
automatic tables are not creating in spring application and application didnt get any error."
automatic tables are not creating in spring application and application didnt get any error."
automatic tables are not creating in spring application and application didnt get any error."
automatic tables are not creating in spring application and application didnt get any error."

Not able to write to the cassandra table using spring batch

I am writing a spring batch process to read the data from the cassandra table and modify it and write the data back to the cassandra table. I am using the same class to read and write the data back to the table. My job is written in an xml file and I am running that xml file itself.I am getting the following error:
The error is shown when I am trying to write the ArrayList back to the table
org.springframework.data.cassandra.mapping.VerifierMappingExceptions:
java.util.ArrayList: Cassandra entities must have the #Table,
#Persistent or #PrimaryKeyClass Annotation
It also shows
at org.springframework.data.cassandra.mapping.BasicCassandraPersistentEntityMetadataVerifier.verify(BasicCassandraPersistentEntityMetadataVerifier.java:45)
at org.springframework.data.cassandra.mapping.BasicCassandraPersistentEntity.verify(BasicCassandraPersistentEntity.java:198)
xml:
<job id="LoadStatusIndicator" job-repository="jobRepository" restartable="false">
<step id="LoadStatus" next="">
<tasklet>
<chunk reader="StatusReader" processor="ItemProcessor" writer="ItemWriter"
commit-interval="1" />
</tasklet>
</step>
</job>
<beans:bean id="ItemWriter" scope="step"
class="com.batch.writer.ItemWriter">
</beans:bean>
<beans:bean id="ItemProcessor" scope="step"
class="com.batch.processor.ItemProcessor">
</beans:bean>
<beans:bean id="Reader" scope="step"
class="com.reader.ItemReader">
<beans:property name="dataSource" ref="CassandraSource" />
</beans:bean>
applicationcontext.xml:
<beans:bean id="CassandraSource" parent="DataSourceParent">
<beans:property name="url" value="jdbc:cassandra://${cassandra.hostName}:${cassandra.port}/${cassandra.keyspace}" />
<beans:property name="driverClassName" value="org.apache.cassandra.cql.jdbc.CassandraDriver" />
</beans:bean>
reader class:
#Override
public List<Item> read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException
{
List<Item> results = new ArrayList<Item>();
try {
results = cassandraTemplate.select(query,Item.class);
} catch (Exception e) {
e.printStackTrace();
}
return results;
}
writer classs:
#Override
public void write(List<? extends Item> item) throws Exception {
try {
cassandraTemplate.update(item);
}catch(Exception e){e.printStackTrace();}
Item class:
#Entity
//#Persistent
//#Transactional
#Table(value ="test")
//#IdClass(ItemPK.class)
//Serializable{
public class Item implements Serializable{
#Id
#PrimaryKeyColumn(name = "id", ordinal = 0, type = PrimaryKeyType.PARTITIONED)
private Integer id;
#PrimaryKeyColumn(name = "name", ordinal = 0, type = PrimaryKeyType.PARTITIONED)
private String name;
#Column(value = "address")
private Float address;
public Item(){}
public Item(Integer id, String name, Float address) {
super();
this.id = id;
this.name = name;
this.address = address;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Float getAddress() {
return address;
}
public void setAddress(Float address) {
this.address = address;
}

HibernateException: saveOrUpdate is not valid without active transaction

Perhaps this question has been asked severally but am not able to find a solution to this. I am new to Spring and trying to working on a simple project to integrate Spring with Hibernate 4 using annotations. Whenever i click the user form to save to DB it throws this exception:
HTTP Status 500 - Request processing failed; nested exception is org.hibernate.HibernateException: saveOrUpdate is not valid without active transaction
What am I doing wrong? My code is below:
User.java
#Entity
#Table(name="SpringUsers")
public class User implements Serializable{
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "userId")
private int id;
#Column(name = "username")
private String username;
#Column(name = "password")
private String password;
#Column(name = "email")
private String email;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
UsDAOImpl.java
#Repository
public class UserDAOImpl implements UserDAO{
#Autowired
private SessionFactory sessionFactory;
public UserDAOImpl(){}
public UserDAOImpl( SessionFactory sessionFactory){
this.sessionFactory= sessionFactory;
}
#Override
#Transactional
public List<User> list() {
List<User> listUser = sessionFactory.getCurrentSession()
.createCriteria(User.class).list();
return listUser;
}
#Override
#Transactional
public void saveOrUpdate(User user) {
sessionFactory.getCurrentSession().saveOrUpdate(user);
}
#Override
#Transactional
public void delete(int id) {
User userToDelete = new User();
userToDelete.setId(id);
sessionFactory.getCurrentSession().delete(userToDelete);
}
#Override
#Transactional
public User get(int i) {
String hql = "from User where id=" + i;
Query query = sessionFactory.getCurrentSession().createQuery(hql);
List<User> listUser = (List<User>) query.list();
if (listUser != null && !listUser.isEmpty()) {
return listUser.get(0);
}
return null;
}
}
user-servlet.xml
<context:component-scan base-package="com.myspringapp.controller"/>
<mvc:annotation-driven/>
<context:annotation-config />
<!-- <tx:annotation-driven />-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="oracle.jdbc.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:#localhost:1521:XE"/>
<property name="username" value="system"/>
<property name="password" value="henry"/>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.OracleDialect</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.current_session_context_class">thread</prop>
</props>
</property>
<property name="annotatedClasses">
<list>
<value>com.myspringapp.model.User</value>
</list>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<constructor-arg ref="sessionFactory"/>
</bean>
<bean id="userDao" class="com.myspringapp.dao.UserDAOImpl">
<constructor-arg ref="sessionFactory"/>
</bean>
<!-- <tx:annotation-driven transaction-manager="transactionManager"/>-->
<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>
Uncomment this line and it should work:
<tx:annotation-driven />

#Valid is not triggering - Spring MVC 3.2

For some reason, its not working. I searched and tried all the solutions found on the net. No dice. Looks like I am missing something.
My Beam:
#Entity
#Table(name="employees")
public class Person {
private Integer person_id;
private String name;
private String name2;
private String email;
private double phone;
private String desc;
#Id
#Max(value=500)
#Column (name="id")
public Integer getPerson_id() {
return person_id;
}
public void setPerson_id(Integer person_id) {
this.person_id = person_id;
}
#NotNull
#NotEmpty
#Column (name="fn")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Column(name="ln")
public String getName2() {
return name2;
}
public void setName2(String name2) {
this.name2 = name2;
}
#Email
#Column (name="em", unique = true)
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
#Column(name="phone")
public double getPhone() {
return phone;
}
public void setPhone(double phone) {
this.phone = phone;
}
#Column (name="de")
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public String toString() {
return getPerson_id() + " - " + getName() + " - " + getName2() + " - " + getEmail();
}
}
Controller Method That handles POST:
#RequestMapping(value="/register", method = RequestMethod.POST, headers="Accept=*/*")
public String registerUer( #javax.validation.Valid Person registerForm, BindingResult br){
System.out.println( "Erros?" + br.hasErrors());
if ( br.hasErrors() ) {
System.out.println(br.getAllErrors());
}
System.out.println(registerForm);
return "thankyou";
}
home.jsp
<form:form action="register.htm" commandName="registerForm" method="post">
Name1: <form:input path="name"/><br />
Name2: <form:input path="name2"/><br />
Email: <form:input path="email"/><br />
Desc: <form:input path="desc" /><br />
Phone: <form:input path="phone" /><br />
<input type="submit" />
</form:form>
application context xml file:
<mvc:annotation-driven />
<context:component-scan base-package="com.springmvcsample"/>
<context:annotation-config/>
<import resource="hibernate_config.xml"/>
<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>
<bean id="contentNegotiationManager"
class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<!-- Turn off working out content type based on URL file extension, should fall back
to looking at the Accept headers -->
<property name="favorPathExtension" value="false" />
</bean>
<bean class="org.springframework.context.support.ResourceBundleMessageSource"
id="messageSource">
<property name="basename" value="messages" />
</bean>
I always get hasErrors() return false
I have hibernate validator (GA jar) file in my classspath. And I see this loaded:
INFO [Version] Hibernate Validator 4.2.0.Final
Am I missing something?
It works as expected if I remove JPA annotations (as I wanted to avoid further configuration for db) and use your form and controller code.
Definitely there is some missing piece, can you try by making a simple pojo with validation annotations and see.

hibernate entity to json

i use Hibernate 4 and Spring 3.
i have two entity.
Book entity
#Entity
#Table(name = "book")
public class Book implements Serializable {
public Book() {
}
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue( strategy = GenerationType.IDENTITY)
private int id;
#ManyToOne()
#JoinColumn( name = "author_id" )
private Author author;
private String name;
private int pages;
#Version
#Column( name = "VERSION")
private int version;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Author getAuthor() {
return author;
}
public void setAuthor(Author author) {
this.author = author;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPages() {
return pages;
}
public void setPages(int pages) {
this.pages = pages;
}
public int getVersion() {
return version;
}
public void setVersion(int version) {
this.version = version;
}
}
and Author entity
#Entity
#Table(name = "author")
public class Author implements Serializable {
public Author() {
}
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue( strategy = GenerationType.IDENTITY)
private int id;
private String name;
#OneToMany( mappedBy = "author", cascade = CascadeType.ALL, orphanRemoval = true)
private Set<Book> books = new HashSet<Book>();
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<Book> getBooks() {
return books;
}
public void setBooks(Set<Book> books) {
this.books = books;
}
public void addBook(Book book) {
book.setAuthor(this);
getBooks().add(book);
}
public void removeBook(Book book) {
getBooks().remove(book);
}
}
and JSON depend in pom.xml
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.1.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-hibernate4</artifactId>
<version>2.1.2</version>
</dependency>
My Root-context is here -
<!-- Root Context: defines shared resources visible to all other web components -->
<context:annotation-config/>
<context:component-scan base-package="org.jar.libs.dao" />
<context:component-scan base-package="org.jar.libs.service" />
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="jspViewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
</bean>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource"
p:driverClassName="com.mysql.jdbc.Driver" p:url="jdbc:mysql://localhost:3306/hibernate"
p:username="root" p:password="root" />
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>org.jar.libs.domain.Book</value>
<value>org.jar.libs.domain.Author</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
</beans>
...servlet-context.xml
<!-- Enables the Spring MVC #Controller programming model -->
<annotation-driven />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
<!-- Resolves views selected for rendering by #Controllers to .jsp resources in the /WEB-INF/views directory -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<context:component-scan base-package="org.jar.libs.controller" />
Controller.
#Controller
#RequestMapping (value = "books/rest")
public class BookController {
#Autowired
private BookService bookService;
// logger
private static final Logger logger = LoggerFactory.getLogger(BookController.class);
#SuppressWarnings("unchecked")
#RequestMapping( method = RequestMethod.GET )
public #ResponseBody List<Book> getBook() {
List<Book> res = bookService.findAll();
return res;
}
}
findAll in my DAO :
public List<Book> findAll() {
Session session = sessionFactory.getCurrentSession();
List<Book> result = (List<Book>) session.createQuery("select c from Book c").list();
return result;
}
in debug i see that method return 2 records, but Spring can not convert result to JSON and return 406 HTTP error. What's wrong?
I attach image what i see in debug. - http://tinypic.com/view.php?pic=35kvi9i&s=6
Generally, when you call getter methods of entity classes(which returns relation object) out of transaction, then you get LazyInitializationExceptions.
That's what might be happening in your case if you are converting entity class objects(retrieved from query) to json out of transaction.
I had same issue, I converted my entity object retrieved by hibernate to json in controller. As controller was out of transaction(Transaction at service layer), while converting to json, getter methods of entity class objects are called and I got LazyInitializationException. Which obstructed object conversion to json, and response was not returned.
My solution, Try this :
#SuppressWarnings("unchecked")
#RequestMapping( method = RequestMethod.GET )
public #ResponseBody List<Book> getBook() {
List<Book> res = bookService.findAll();
for(Book book : res) {
book.getAuthor().setBooks(null);
}
return res;
}
As others have suggested,
I would really not advise you to try to JSON serialize (or actually perform any serialization) of hibernate entities.
You must remember that the fetched entities are actually "proxified" objects (Hibernate uses ASM, CGLIB and other "dynamic proxiy" frameworks).
As a result for example, collections get replaced with [PersistenceBags] which may be initialized "lazily" , and cause you hibernate exceptions 1.
But the problems do not stop there, you may see issues when trying to serialize an Hibernate custom type
I know this might sound you like writing "boillerplate" code but you might end up coding DTOs - data transfer objects which will take the entity returned from your DAL, and transform them to an object that can be serialized.
You can use a framework like dozer in order to ease development of serialization between an entity to a DTO.
Try using these two Jackson artifacts instead
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.9</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<version>1.9.9</version>
</dependency>
Also on your controller try by changing it to -
#SuppressWarnings("unchecked")
#RequestMapping( method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE )
public #ResponseBody List<Book> getBook() {
Lastly, make sure your view is making a json request.

Categories

Resources