Retrieve results JAX-RS + Jersey + Jackson - jackson

I have this entity class
#Entity
#XmlRootElement
#Table(name="user")
#NamedQuery(name="User.findAll", query="SELECT u FROM User u")
public class User implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="id_user", unique=true, nullable=false)
private String idUser;
#Column(nullable=false, length=50)
private String docnum;
#Column(nullable=false, length=50)
private String email;
#Column(nullable=false, length=50)
private String firstname;
#Column(nullable=false, length=50)
private String lastname;
#Column(nullable=false, length=45)
private String pwd;
//bi-directional many-to-many association to Transaction
#ManyToMany
#JoinTable(
name="transaction_users"
, joinColumns={
#JoinColumn(name="user", nullable=false)
}
, inverseJoinColumns={
#JoinColumn(name="transaction", nullable=false)
}
)
private List<Transaction> transactions;
public User() {
}
public String getIdUser() {
return this.idUser;
}
public void setIdUser(String idUser) {
this.idUser = idUser;
}
public String getDocnum() {
return this.docnum;
}
public void setDocnum(String docnum) {
this.docnum = docnum;
}
public String getEmail() {
return this.email;
}
public void setEmail(String email) {
this.email = email;
}
public String getFirstname() {
return this.firstname;
}
public void setFirstname(String firstname) {
this.firstname = firstname;
}
public String getLastname() {
return this.lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
public List<Transaction> getTransactions() {
return this.transactions;
}
public void setTransactions(List<Transaction> transactions) {
this.transactions = transactions;
}
}
generated from a database table. Then i have this rest service
#Path("service/2.0")
public class ServiceTest {
#GET
#Path("/users")
#Produces(MediaType.APPLICATION_JSON)
public Response getUser() {
EntityManager entityManager = EntityManagerUtil.getEntityManager();
entityManager.getTransaction().begin();
Query q = entityManager.createQuery("SELECT u FROM User u");
#SuppressWarnings("unchecked")
List<User> listOfUser = q.getResultList();
System.out.print(listOfUser);
return Response.ok(listOfUser).build();
}
I'm (supposed) to be using the jackson API to handle json but i'm not using maven. For this reason, i've added in my buildpath the following .jars:
jackson-annotations-2.9.3.jar
jackson-core-2.9.3.jar
jackson-databind-2.9.3.jar
jackson-jaxrs-base-2.9.3.jar
jackson-module-jaxb-annotations-2.9.3.jar
jersey-media-json-jackson-2.26.jar
jackson-jaxrs-json-provider-2.9.3.jar
Then i have an ApplicationConfig.java class
package prova;
import com.fasterxml.jackson.jaxrs.json.*;
import org.glassfish.jersey.server.ResourceConfig;
import javax.ws.rs.ApplicationPath;
#ApplicationPath("rest")
public class ApplicationConfig extends ResourceConfig {
public ApplicationConfig() {
packages("com.fasterxml.jackson.jaxrs.json");
packages("prova");
}
}
When i try to submit a GET request with postman, i obtain an "HTTP 500 internal server error" with the description:
"The server encountered an unexpected condition that prevented it from fulfilling the request."
While from the eclipse console i can see
[EL Fine]: sql: 2017-12-16 17:44:54.251--ServerSession(1869059368)--
Connection(771012214)--Thread(Thread[http-nio-8080-exec-80,5,main])--
SELECT id_user, DOCNUM, EMAIL, FIRSTNAME, LASTNAME, PWD FROM user
[prova.User#3c713cb0, prova.User#49e51730, prova.User#d9ecdd7,
prova.User#383fe468]dic 16, 2017 5:44:54
PM org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWr
iterInterceptor aroundWriteTo
GRAVE: MessageBodyWriter not found for media type=application/json,
type=class java.util.Vector, genericType=class java.util.Vector.
So what i can deduce is that the query is correctly executed and it returns an array of 4 object (prova is the name of my entity manager) but then i have the GRAVE:MessageBodyWriter Error
What the hell i'm not doing correctly?why i can not retrieve my JSON data?
Thanks
UPDATE
Following the advice, i've modified the GET resource into
#GET
#Path("/users")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public String getUser() {
return String.valueOf(10+4);
}
and submitting the GET request gives me the expected JSON answer from Postman "14"....
Can the problem be the conversion of a List into Json?if yes, what to do?
Thanks
UPDATE 2
I've edited the code of the REST resource in this way:
#GET
#Path("/users")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public String getUser() {
EntityManager entityManager = EntityManagerUtil.getEntityManager();
entityManager.getTransaction().begin();
Query q = entityManager.createQuery("SELECT u FROM User u");
List<User> listOfUser = q.getResultList();
System.out.print(listOfUser);
if (listOfUser.isEmpty()) {
System.out.println("VOID LIST");
entityManager.close();
return String.valueOf(2);
}
for (User user : listOfUser) {
System.out.println(user.getFirstname());
System.out.println("---");
}
return String.valueOf(3);
}
The postman Output is "3" so, everything fine while the consoloe output is:
[EL Fine]: sql: 2017-12-17 13:48:33.214--ServerSession(286337061)--
Connection(2132504260)--Thread(Thread[http-nio-8080-exec-2,5,main])--
SELECT id_user, DOCNUM, EMAIL, FIRSTNAME, LASTNAME, PWD FROM USER
[prova.User#2d3017ff, prova.User#6361d00, prova.User#7ab0944a,
prova.User#5945162f]
matteo
---
tony
---
bruce
---
peter
---
which is perfectly consistent with what i have in the table of the DB... :(

Try to convert your response entity in an array of users. There is proper equivalent for array in json.
Other way ist to have a wrapper class for your list of users.
#XmlType
#XmlRootElement
class Wrapper {
#XmlElement
List<User> users;
}
Return this in your response.

Related

Get entitymanager in jax-rs subresource?

What is the correct way to get entitymanager in a jax-rs subresource?
When I go to http://localhost/api/roots/1/branches the logger outputs null for the em. Also tried passing em into the constructor and that "works" as it is not null, but when I try to persist a new branch it throws a javax.persistence.TransactionRequiredException: No active transaction for PuId=TestAPIEAR#TestAPI.war#TestAPI
RootResource.java
#Path(value = "/roots")
#Stateless
public class RootResource {
#Context
UriInfo uriInfo;
#PersistenceContext(unitName = "TestAPI")
private EntityManager em;
#GET
#Produces(MediaType.APPLICATION_JSON)
public Collection<Root> getRoots() {
TypedQuery<Root> query = em
.createNamedQuery("Root.findAll", Root.class);
List<Root> rootList = query.getResultList();
return rootList;
}
// Sub Resources
#Path("{rootid}/branches")
#Produces(MediaType.APPLICATION_JSON)
public BranchResource getBranches() {
return new BranchResource();
}
}
BranchResource.java
#Path("/")
#Stateless
public class BranchResource {
#PersistenceContext(unitName = "TestAPI")
private EntityManager em;
#GET
#Produces(MediaType.APPLICATION_JSON)
public Collection<Branch> getBranches(#Context UriInfo uriInfo,
#PathParam("rootid") long rootId) {
logger.info("Entity Manager: " + em);
TypedQuery<BriefcaseContent> query = em.createNamedQuery(
"Branch.findAllforRoot", Branch.class);
query.setParameter("rootid", rootId);
List<Branch> branchList = query.getResultList();
return branchList;
}
}

Spring-data-solr config

i met a problem in Studying with Spring data solr,this is my Configuration Class:
#Configuration
#EnableSolrRepositories(basePackages={"cn.likefund.solr.repository"}, multicoreSupport=true)
public class SolrContext {
static final String SOLR_HOST = "http://192.168.11.157:8080/solr";
#Bean
public SolrClient solrClient() {
return new HttpSolrClient(SOLR_HOST);
}
}
and this is my Repository:
package cn.likefund.solr.repository;
import java.util.List;
import org.springframework.data.solr.repository.SolrCrudRepository;
import cn.likefund.solr.model.Activity;
public interface ActivityRepository extends SolrCrudRepository<Activity, String>{
List<Activity> findByName(String name);
}
when I start the application,the message in console is this
error
When I delete the method findByName in the repository,the application start with no problem, i just want to the method findByName worked,anybody know what should i do with this problem?
here is the Activity Class:
#Entity
#SolrDocument(solrCoreName ="core_activity")
public class Activity implements Serializable{
private static final long serialVersionUID = 1566434582540525979L;
#Id
#Field(value = "id")
private String id;
#Field(value = "CREATEDT")
private String createdt;
#Indexed
#Field(value = "NAME")
private String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getCreatedt() {
return createdt;
}
public void setCreatedt(String createdt) {
this.createdt = createdt;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
So, obviously the CrudRepository is not created .
when you delete the findByName, can you manually query your repo ? (just to be sure the problem comes from the method, and not the SOLR schema)
have you tried to annotate annotate the method to explicitly set the query ? Something like
#Query("NAME:?0")
List findByName(String name);

Glassfish - cannot remove entity using JPA

In my exploration of JPA, I have the code below (which I understand should not be used in production). Running my code produces the following error:
java.lang.IllegalStateException:
Exception Description: Cannot use an EntityTransaction while using JTA.
The Resource code is as follows:
#Path("users")
public class UsersAPI {
#Context
UriInfo uriInfo;
#Inject
UserBean accountsBean;
#GET
#Path("deduplicate")
public Response deduplicateDB(){
List<UserProfile> profiles = accountsBean.getAll();
int profilesNum = profiles.size();
for(int i = 0; i < profilesNum; ++i){
for(int k = 0; k < profilesNum; ++k){
if(i != k){ //if it's not the same profile
if(profiles.get(i).getUsername().equals(profiles.get(k).getUsername())){
accountsBean.remove(profiles.get(k));
profiles.remove(k);
}
}
profilesNum = profiles.size();
}
}
return Response.ok().build();
}
}
The code in the ProfilesBean is as follows:
#Local
#Stateless
public class UserBean {
#PersistenceContext
EntityManager eManager;
public void save(UserProfile data){
eManager.merge(data);
}
public void remove(UserProfile data){
eManager.getTransaction().begin();
eManager.remove(data);
eManager.getTransaction().commit();
}
public List<UserProfile> getAll(){
Query q = eManager.createQuery("SELECT profile FROM Users profile");
return (List<UserProfile>)q.getResultList();
}
}
Here is the code for the Entity class:
#Entity(name="Users")
public class UserProfile {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
Long id;
String password;
#Column(unique=true)
String username;
public UserProfile(String username){
setUsername(username);
}
public UserProfile(){
this(null);
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
It seems like the error comes from my misusing the platform somehow. How can I fix this code and not misuse the platform in the future?
If you are using JTA as transaction-type in persistence.xml file just leave JTA handles your transactions
public void remove(UserProfile data){
eManager.remove(eManager.merge(data));
}
UPDATE:
In a more clear solution you could use "find", but you need to provide the object id
public void remove(UserProfile data){
UserProfile e = em.find(UserProfile.class, data.getId());
eManager.remove(e);
}

Getting class cast exception when doing a POST request using JAX-RS with hibernate backend

I have a simple User POJO class, its definition is as follows:
package models;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#Entity
#XmlRootElement
#Table(name="USER",uniqueConstraints={#UniqueConstraint(columnNames="email")})
public class User {
#XmlElement
private String name;
#Id
#XmlElement
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
#XmlElement
private String email;
#XmlElement
private int age;
#Override
public String toString() {
return "User [name=" + name + ", id=" + id + ", email=" + email + ", age=" + age + "]";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
and my resource mapping is as follows:
#POST
#Produces(MediaType.TEXT_HTML)
#Consumes(MediaType.APPLICATION_JSON)
#Path("/Person")
public Response insertPerson(User user) {
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
int uid = (Integer)session.save(user);
tx.commit();
session.close();
return Response.status(201).entity(uid).build();
}
When i do a post request using PostMan i am getting this exception on server:
Dec 20, 2015 9:44:42 AM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [Jersey Web Application] in context with path [/expenseManagement] threw exception [Exception [EclipseLink-6065] (Eclipse Persistence Services - 2.6.0.v20150309-bf26070): org.eclipse.persistence.exceptions.QueryException
Exception Description: Cannot add the object [User [name=manjunath, id=100, email=manjunath#gmail.com, age=15]], of class [class models.User], to container [class models.User].
Internal Exception: java.lang.ClassCastException: models.User cannot be cast to java.util.Collection] with root cause
java.lang.ClassCastException: models.User cannot be cast to java.util.Collection
I have provided message body readers as well, I don't know where i am going wrong, can someone please help.
The content you send is surrounded by [ and ] marking it an array, not an object. Try sending only this String:
{"name":"manjunath", "age":15, "id":100, "email":"manjunath#gmail.com"}
Good Luck

Web Services: Unexpected EOF in prolog - I get this when I use Apache CXF and a method that has a POJO parameter

I have the following login service interface:
#Path("/loginService/")
#WebService(serviceName = "LoginService", name = "LoginService", targetNamespace = "http://ws.test.com")
public interface LoginService {
/**
* Takes an authentication request, and returns an authentication response.
* In the event of an authentication failure, an HTTP status of 401 should
* be returned.
*
* #param request
* #return
*/
#WebMethod
#GET
#Path("/")
public AuthenticationResponse login(#WebParam(name = "request") final AuthenticationRequest request);
}
I have the following in my spring file
<bean id="loginService" autowire="autodetect"
class="com.test.mobile.webservices.authentication.LoginServiceImpl">
</bean>
<jaxws:endpoint id="LoginServiceEndpoint"
serviceName="LoginService"
implementorClass="com.test.mobile.webservices.authentication.LoginService"
implementor="#loginService"
address="/loginService">
<jaxws:serviceFactory>
<ref bean="jaxws-and-aegis-service-factory"/>
</jaxws:serviceFactory>
</jaxws:endpoint>
When I attempt to hit the following URL:
http://localhost:8080/TPCMobileWS/api/rest/loginService?wsdl
I get the following message:
JAXBException occurred : Unexpected EOF in prolog at [row,col
{unknown-source}]: [1,0]. Unexpected EOF in prolog at [row,col
{unknown-source}]: [1,0].
If I remove completely the "request" parameter in the login method, the URL hit above works just fine... no error, shows the right data.
What am I doing wrong when passing that POJO? It just has a couple primitive types in it with getters and setters. Am I missing some annotations?
Your help is MUCH appreciated!
Below is the Authentication Request:
package com.test.mobile.webservices.authentication;
import java.io.Serializable;
import javax.xml.bind.annotation.XmlRootElement;
import com.test.mobile.webservices.Localization;
#XmlRootElement
public class AuthenticationRequest implements Serializable {
private static final long serialVersionUID = 1L;
private String username;
private Localization.Country country;
private String password;
public AuthenticationRequest() {
}
/**
* For now, this is the consultant's ID.
*
* #return
*/
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
/**
* The country that the consultant is associated with, as a two letter ISO
* country code.
*
* #return
*/
public Localization.Country getCountryCode() {
return country;
}
public void setCountryCode(Localization.Country country) {
this.country = country;
}
/**
* The consultant's password.
*
* #return
*/
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}