RESTEasy Could not find MessageBodyWriter for response object of type: <Entity Class> of media type: application/json - rest

I'm trying to implement a rest endpoint using rest easy. This is a GET endpoint,
#Controller
#Path("/api")
public class TestController {
private static final Log LOG = LogFactory.getLog(TestController .class);
#GET
#Path("/test")
#Produces(MediaType.APPLICATION_JSON)
public Response getTest() {
LOG.info(" inside test");
Response r = null;
try {
Test test = new Test();
test.setId(1L);
test.setName("test");
test.setAge("20");
r = Response.ok(test).build();
} catch (Exception e){
LOG.error(e);
}
return r;
}
}
Below is the entity class which I'm trying to return
#XmlRootElement
public class Test {
#XmlElement(name = "id")
private Long id;
#XmlElement(name = "name")
private String name;
#XmlElement(name = "age")
private String age;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
}
Getting below error when the endpoint is called from a rest client.
Could not find MessageBodyWriter for response object of type: com.package.Test of media type: application/json
These are some dependencies I have added which I believe would be useful for this.
httpclient-4.0.3.jar
httpcore-4.0.1.jar
jackson-core-asl-1.6.3.jar
jackson-jaxrs-1.9.13.jar
jackson-jaxrs-json-provider-2.2.1.jar
jackson-mapper-asl-1.6.3.jar
jackson-xc-1.6.3.jar
jaxrs-api-3.0.12.Final.jar
jboss-logging-3.3.1.Final.jar
jcip-annotations-1.0.jar
resteasy-jaxb-provider-3.1.0.Final.jar
resteasy-jettison-provider-2.3.1.GA.jar
resteasy-spring-2.2.1.GA.jar
scannotation-1.0.3.jar
Does anyone has an idea why this kind of error coming. endpoint is able return a plain string as a response.

jackson-jaxrs-json-provider contains the MessageBodyReader/Writer to handle JSON/POJO conversion. But you still need to register its JacksonJaxbJsonProvider with your application.
If you are using RESTEasy, you can also just add the resteasy-jackson-provider dependency to your project and it will automatically register the JacksonJaxbJsonProvider so you don't need to explicitly do it. The dependency also adds a few other useful items. So your best bet is to just add the dependency.

Related

POST REST request including a foreign key OnToMany Mapping

i'm new to Springboot. I'm trying to implement a simple REST api using :
-Springboot, JPA & rest along with hibernate
I have a 2 tables database, Notebook that contains 1 to many notes
I already setup the 2 tables and relationships. I also created a NotebookRepository and NoteRepository to get basic CRUD operations via the springboot rest. The Database connection and relationships are functionning
but i don't know how to add a new note (it has a notebook_id foreign key which msut NOT be NULL) and everytime i tryto post something along these lines
{
"title:"abc",
"text":"whatever",
"notebook":{
"id":2
}
}
i get this error :
Caused by: java.sql.SQLIntegrityConstraintViolationException: Column 'notebook_id' cannot be null
#Entity
#Table(name="notebook")
public class NoteBook {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="id")
private int id;
#Column(name="name")
private String name;
#OneToMany(mappedBy="notebook", cascade=CascadeType.ALL)
List<Note> notes;
public NoteBook() {
}
public NoteBook(String name) {
this.name = name;
}
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 List<Note> getNotes() {
return notes;
}
public void setNotes(List<Note> notes) {
this.notes = notes;
}
public void addNote(Note note) {
if(notes == null) {
notes = new ArrayList<>();
}
note.setNotebook(this);
notes.add(note);
}
#Entity
#Table(name="note")
public class Note {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="id")
private int id;
#Column(name="title")
private String title;
#Column(name="text")
private String text;
#ManyToOne(cascade={CascadeType.MERGE, CascadeType.DETACH, CascadeType.PERSIST, CascadeType.REFRESH})
#JoinColumn(name="notebook_id")
private NoteBook notebook;
public Note() {
}
public Note(String title, String text) {
this.title = title;
this.text = text;
}
#RepositoryRestResource(collectionResourceRel = "note", path = "notes")
public interface NoteRepository extends JpaRepository<Note, Integer>{
//No code...
}
#RepositoryRestResource(collectionResourceRel = "notebook", path = "notebooks")
public interface NotebookRepository extends JpaRepository<NoteBook, Integer>{
}
The problem is that the class Note doesn't have a constructor with NoteBook parameter to pass the created NoteBook object to, so the solution is to add this constructor:
public Note(String title, String text, NoteBook noteBook) {
this.title = title;
this.text = text;
this.noteBook = noteBook;
}
and it's enough to send the JSON object as you do, but just be aware of case-sensitivity:
{ "title:"abc", "text":"whatever", "noteBook":{ "id":2 } }
I think you need to add referencedColumnName = "id" for JoinColumn annotation for notebook field in Note class.
Maybe you have problem with IDENTITY generation type. See this problem with null pointer

Spring boot CrudRepository save - exception is org.hibernate.type.SerializationException: could not serialize

Not sure why I have an issue here, but when I save with a CrudRepository with these objects, I get the SerializationException (with no further information). Can someone take a look at my objects and offer me some insight into why they can't serialize? My pom.xml is attached last as well in case that helps somehow. I'm using a Postgres database.
EDIT: The database and now - tables are created, but objects are not creating rows.
The actual CrudRepository interface:
public interface AccountRepository extends CrudRepository<ZanyDishAccount, String> {}
ZanyDishAccount entity:
#Entity
public class ZanyDishAccount {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private Long id; // internal id of the customer account for a Zany Dish subscription
private String status;
#OneToOne(cascade=CascadeType.ALL, fetch = FetchType.EAGER)
#JoinColumn(name = "company_id")
private Company company;
#OneToOne(cascade=CascadeType.ALL, fetch = FetchType.EAGER)
#JoinColumn(name = "order_id")
private Order order;
public ZanyDishAccount() {}
public ZanyDishAccount(Company company, Order order) {
this.company = company;
this.order = order;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Company getCompany() {
return company;
}
public void setCompany(Company company) {
this.company = company;
}
public Order getOrder() {
return order;
}
public void setOrder(Order order) {
this.order = order;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
#Override
public String toString()
{
return "ClassPojo [id = "+id+ ", company = " + company + ", status = " + status + "]";
}
}
Company entity:
#Entity
public class Company {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
Long id;
private String phoneNumber;
private String website;
private String name;
private String uuid;
private String country;
public Company() {}
public Company(String phoneNumber, String website, String name, String uuid, String country) {
this.phoneNumber = phoneNumber;
this.website = website;
this.uuid = uuid;
this.country = country;
}
public String getPhoneNumber ()
{
return phoneNumber;
}
public void setPhoneNumber (String phoneNumber)
{
this.phoneNumber = phoneNumber;
}
public String getWebsite ()
{
return website;
}
public void setWebsite (String website)
{
this.website = website;
}
public String getName ()
{
return name;
}
public void setName (String name)
{
this.name = name;
}
public String getUuid ()
{
return uuid;
}
public void setUuid (String uuid)
{
this.uuid = uuid;
}
public String getCountry ()
{
return country;
}
public void setCountry (String country)
{
this.country = country;
}
#Override
public String toString()
{
return "ClassPojo [phoneNumber = "+phoneNumber+", website = "+website+", name = "+name+", uuid = "+uuid+", country = "+country+"]";
}
}
Order entity:
#Entity
#Table(name = "_order")
public class Order {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
Long id;
private String pricingDuration;
private Items[] items;
private String editionCode;
public Order() {}
public Order(String pricingDuration, Items[] items, String editionCode) {
this.pricingDuration = pricingDuration;
this.items = items;
this.editionCode = editionCode;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getPricingDuration ()
{
return pricingDuration;
}
public void setPricingDuration (String pricingDuration)
{
this.pricingDuration = pricingDuration;
}
public Items[] getItems ()
{
return items;
}
public void setItems (Items[] items)
{
this.items = items;
}
public String getEditionCode ()
{
return editionCode;
}
public void setEditionCode (String editionCode)
{
this.editionCode = editionCode;
}
#Override
public String toString()
{
return "ClassPojo [pricingDuration = "+pricingDuration+", items = "+items+", editionCode = "+editionCode+"]";
}
}
Thanks for your help!
Mike
Hm, this seems multi-faceted. Let's see if I can help at all. Last thing first...
No tables being created automatically.
I would take a look at this section in Spring's docs for the most basic approach: Initialize a database using Hibernate. For example, spring.jpa.hibernate.ddl-auto: create-drop will drop and re-create tables each time the application runs. Simple and easy for initial dev work. More robust would be leveraging something like Flyway or Liquibase.
Serialization issue
So without logs, and the fact that you have no tables created, the lack of a persistence layer would be the assumed culprit. That said, when you have tables and data, if you do not have a repository for all of the related tables, you'll end up with a StackOverflow error (the serialization becomes circular). For that, you can use #JsonBackReference (child) and #JsonManagedReference (parent). I have been successful using only #JsonBackReference for the child.
Items[]
I'm not sure what Item.class looks like, but that looks like an offensive configuration that I missed the first round.
Change private Items[] items; to private List<Item> items = new ArrayList<Item>();. Annotate with #ElementCollection.
Annotate Item.class with #Embeddable.

Play 2.3.4 Java - JPA oneToMany not saving foreign key. Please check where am going wrong

Here are the entity snippet.......Ignore DaoObject..it just adds autogenerated Id to each entity it subclasses.
I've highlighted which is necessary to persist Content. Eventullally it is not able to add value to contentid column in streams table. It though adds a row to both content and streams table with below code..
Please check and help me troubleshoot the problem
Content newContent = TestHelper.contentFactory(null, "streamForCREATE_IT", xxxx, 100);
Stream stream = TestHelper.streamFactory(null, "name", "appname",);
**stream.setContent(newContent);
List<Stream> streams = new ArrayList<Stream>();
streams.add(stream);
newContent.setStreams(streams);**
#Entity
public class Content extends DaoObject {
public Content() {
};
private String name;
private ContentType type;
#OneToMany(fetch = FetchType.EAGER, mappedBy = "content", cascade = {CascadeType.PERSIST,CascadeType.MERGE}, orphanRemoval = true)
#JsonManagedReference
private List<Stream> streams = new ArrayList<Stream>();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Stream> getStreams() {
return streams;
}
public void setStreams(List<Stream> streams) {
this.streams = streams;
}
public void addStream(Stream newStream) {
if (streams == null) {
streams = new ArrayList<Stream>();
}
newStream.setContent(this);
streams.add(newStream);
}
}
#Entity
public class Stream extends DaoObject {
public Stream() {
}
#ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinColumn(name = "contentid")
#JsonBackReference
private Content content;**
private String name;
private String appName;
public Content getContent() {
return content;
}
public void setContent(Content content) {
this.content = content;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAppName() {
return appName;
}
public void setAppName(String appName) {
this.appName = appName;
}
}
Here is the image from mysql workbench.
Damn it was stupid. Am testing REST API where this is happening and I did set streams for content and each stream's content correctly but that was all happening before JSON transformation. When this association is recreated in dao it worked. Thanks #AndreiI for asking correct questions which helped me resolve this.

Bidirectional one to one mapping in GAE using JDO?

How can I implement a bidirectional one-to-one mapping using Google Application Engine (GAE) using Java Data Objects (JDO)?
I have a User class which holds contactInfo object and a ContactInfo class that holds a user object
#PersistenceCapable(identityType ="APPLICATION", detachable = "true")
public class User{
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Long id;
private String name;
#Persistent(dependent = "true")
private ContactInfo child;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public ContactInfo getChild() {
return child;
}
public void setChild(ContactInfo child) {
this.child = child;
}
}
#PersistenceCapable(identityType ="APPLICATION", detachable = "true")
public class ContactInfo {
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Key id;
#Persistent(mappedBy = "child")
private User parent;
private String contactDetail;
public Key getId() {
return id;
}
public void setId(Key id) {
this.id = id;
}
public String getContactDetail() {
return contactDetail;
}
public void setContactDetail(String contactDetail) {
this.contactDetail = contactDetail;
}
}
Following error i am getting while testing API from API explorer
com.google.appengine.repackaged.org.codehaus.jackson.map.JsonMappingException: Infinite recursion (StackOverflowError) (through reference chain: com.demo.jdo.ContactInfo[\"user\"]->com.demo.jdo.User[\"contactInfo\"]->com.demo.jdo.ContactInfo[\"user\"]-
Standard JDO 1-1 bidir is simply found from http://www.datanucleus.org/products/accessplatform_3_1/jdo/orm/one_to_one.html#bi
GAE ought to be no different in this respect; last time I used it (maybe 3 yrs ago) they had some tests, think those under here http://code.google.com/p/datanucleus-appengine/source/browse/#svn%2Ftrunk%2Ftests%2Fcom%2Fgoogle%2Fappengine%2Fdatanucleus
Your question provides no definition of what you have tried in terms of annotations
Got the Solution, problem was with wrong use of mappedBy & presence of getter and setter of parent object in child.
#Persistent(mappedBy = "") annotation should only be at non-owner side
In on-owner/ child side there should not be any getter/setter present for owner/parent object.
Working code:
User.java
import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.IdentityType;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;
#PersistenceCapable(identityType = IdentityType.APPLICATION, detachable = "true")
public class User {
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Long id;
private String name;
#Persistent(dependent = "true")
private ContactInfo contactInfo;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public ContactInfo getContactInfo() {
return contactInfo;
}
public void setContactInfo(ContactInfo contactInfo) {
this.contactInfo = contactInfo;
}
}
ContactInfo.java
import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.IdentityType;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;
import com.google.appengine.api.datastore.Key;
#PersistenceCapable(identityType = IdentityType.APPLICATION, detachable = "true")
public class ContactInfo {
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Key id;
#Persistent(mappedBy = "contactInfo")
/*
* Important: Do not create getter and setters for this object else
* bidirectional mapping gives error
*/
private User user;
private String contactDetail;
public Key getId() {
return id;
}
public void setId(Key id) {
this.id = id;
}
public String getContactDetail() {
return contactDetail;
}
public void setContactDetail(String contactDetail) {
this.contactDetail = contactDetail;
}
}

Passing multiple variables from servlet to client

I hope someone can assist me with this. I'm trying to pass an customer id and customer name from a database result using rpc in gwt to the client. I found a way to pass one variable but I can't find a way to pass them both where the id is attached to the name. Can someone post a code example on how to do this. If you need more info let me know.
That is a simple java limitation. Just wrap the 2 fields in an object.
As David Nouls said, you could just use an object, e.g.
import com.google.gwt.user.client.rpc.IsSerializable;
public class Customer implements IsSerializable {
private String id;
private String name;
public Customer(String id, String name) {
this.id = id;
this.name = name;
}
public void setId(String id) {
this.id = id;
}
public String getId() {
return id;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}