Why this REST service is not working? - java

package model;
import java.net.URI;
import java.util.Collection;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import javax.ws.rs.BadRequestException;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.NotFoundException;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
#Path("/item")
#Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
#Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
#Stateless
public class InfoRestService {
// the PersistenceContext annotation is a shortcut that hides the fact
// that, an entity manager is always obtained from an EntityManagerFactory.
// The peristitence.xml file defines persistence units which is supplied by
// name
// to the EntityManagerFactory, thus dictating settings and classes used by
// the
// entity manager
#PersistenceContext(unitName = "Task")
private EntityManager em;
// Inject UriInfo to build the uri used in the POST response
#Context
private UriInfo uriInfo;
#POST
public Response createItem(PersonInfo item) {
if (item == null) {
throw new BadRequestException();
}
em.persist(item);
// Build a uri with the Item id appended to the absolute path
// This is so the client gets the Item id and also has the path to the
// resource created
URI itemUri = uriInfo.getAbsolutePathBuilder().path(item.getId()).build();
// The created response will not have a body. The itemUri will be in the
// Header
return Response.created(itemUri).build();
}
#GET
#Path("{id}")
public Response getItem(#PathParam("id") String id) {
PersonInfo item = em.find(PersonInfo.class, id);
if (item == null) {
throw new NotFoundException();
}
return Response.ok(item).build();
}
// Response.ok() does not accept collections
// But we return a collection and JAX-RS will generate header 200 OK and
// will handle converting the collection to xml or json as the body
#GET
public Collection<PersonInfo> getItems() {
TypedQuery<PersonInfo> query = em.createNamedQuery("PersonInfo.findAll",
PersonInfo.class);
return query.getResultList();
}
#PUT
#Path("{id}")
public Response updateItem(PersonInfo item, #PathParam("id") String id) {
if (id == null) {
throw new BadRequestException();
}
// Ideally we should check the id is a valid UUID. Not implementing for
// now
item.setId(id);
em.merge(item);
return Response.ok().build();
}
#DELETE
#Path("{id}")
public Response deleteItem(#PathParam("id") String id) {
PersonInfo item = em.find(PersonInfo.class, id);
if (item == null) {
throw new NotFoundException();
}
em.remove(item);
return Response.noContent().build();
}
}
package model;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlRootElement;
/**
* The persistent class for the person_info database table.
*
*/
#Entity
#XmlRootElement
#Table(name="person_info")
#NamedQuery(name="PersonInfo.findAll", query="SELECT p FROM PersonInfo p")
public class PersonInfo implements Serializable {
private static final long serialVersionUID = 1L;
#Id
private String id;
private String email;
#Column(name="first_name")
private String firstName;
#Column(name="last_name")
private String lastName;
public PersonInfo() {
}
public String getId() {
return this.id;
}
public void setId(String id) {
this.id = id;
}
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;
}
}
persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="Task">
<jta-data-source>jdbc/DBtest</jta-data-source>
<class>model.PersonInfo</class>
</persistence-unit>
</persistence>
and the other class is Application
package model;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
#ApplicationPath("rest")
public class ApplicationConfig extends Application{
}
I really have no idea, the connections are made ok .. I'm using Glassfish 4 server and MySQL database... code is deploying but when I want to access the localhost:8080/Task/.. (my app) the only thing it says is this:
"HTTP Status 404 - Not Found / Type Status report
messageNot Found
descriptionThe requested resource is not available."

The code you supplied is working (when commenting out the persistence related stuff), I guess you are just confusing something.
The #ApplicationPath annotation sets the root context which comes after your project name.
If you project name really is Task you have to use this URL: http://localhost:8080/Task/rest/item
Otherwise: http://localhost:8080/YOUR_PROJECT_NAME/rest/item
See also:
How to set up JAX-RS Application using annotations only (no web.xml)?

Related

Angular HttpErrorResponse GET Request

I have a simple Quarkus project and want to show the data in an Angular table with HttpClient. I also have a CORS Filter. Anyway, I get the following error:
Angular table with no date, HttpErrorResponse Status 0
service.ts
import { HttpClient } from '#angular/common/http';
import { Injectable } from '#angular/core';
import { Observable } from 'rxjs';
import { School } from './model/school';
#Injectable({
providedIn: 'root'
})
export class SchoolService {
url = "localhost:8080/school"
constructor(public http: HttpClient) { }
getAll(): Observable<School[]> {
return this.http.get<School[]>(this.url);
}
getById(id: number): Observable<School> {
const url = "locahlost:8080/school/{id}";
return this.http.get<School>(url);
}
}
ts of component
import { Component, OnInit } from '#angular/core';
import { School } from '../model/school';
import { SchoolService } from '../school.service';
#Component({
selector: 'app-dashboard',
templateUrl: './dashboard.component.html',
styleUrls: ['./dashboard.component.css']
})
export class DashboardComponent implements OnInit {
schools: School[] = [];
constructor(public schoolService: SchoolService) { }
ngOnInit(): void {
this.schoolService.getAll().subscribe(e => {
this.schools = e;
});
}
}
html
<table>
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Street</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let school of schools">
<td>{{school.id}}</td>
<td>{{school.name}}</td>
<td>{{school.street}}</td>
</tr>
</tbody>
</table>
server model
package model;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
#Entity
public class School {
#Id
#GeneratedValue
private int id;
private String name;
private String street;
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 String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
}
resource
package rest;
import model.School;
import javax.inject.Inject;
import javax.transaction.Transactional;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import java.util.List;
#Path("school")
#Produces(MediaType.APPLICATION_JSON)
#Transactional
public class SchoolResource {
#Inject
SchoolDao dao;
#GET
public List<School> getAll() {
return dao.getAll();
}
#Path("id")
#GET
public School getById(#PathParam("id") int id) {
return dao.getById(id);
}
}
dao
package rest;
import model.School;
import javax.enterprise.context.Dependent;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import java.util.List;
#Dependent
public class SchoolDao {
#Inject
EntityManager em;
public List<School> getAll() {
return em.createQuery("select s from School s", School.class).getResultList();
}
public School getById(int id) {
return em.find(School.class, id);
}
}
Thank you in advance, I think the problem must be on the server, because I tried showing data with a JSON file instead of Quarkus data already, and it does work.
As #R.Richards mentioned in a comment, putting "http://" in front of the url in the service file solved the problem.

Dropwizard: How to add a custom validation for GET / PUT

I have a dropwizard service in which I am trying to implement request validation, and below is the code for same.
import com.google.common.collect.ImmutableMap;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import com.fasterxml.jackson.annotation.JsonProperty;
import javax.ws.rs.Path;
import javax.ws.rs.QueryParam;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.Produces;
import javax.ws.rs.Consumes;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
#Path("/system-info")
#Produces(MediaType.APPLICATION_JSON)
public class SystemInfo {
#GET
#Path("/get")
public Response testValidation(#QueryParam("name") String name,
#QueryParam("phoneNo") Long phoneNo,
#QueryParam("email") String email,
#QueryParam("password") String password) {
if(email == null) {
return Response.ok(ImmutableMap.of("status", "email missing")).build();
}
//bunch of other validations
return Response.ok(ImmutableMap.of("status", "ok")).build();
}
#POST
#Consumes(MediaType.APPLICATION_JSON)
#Path("/post")
public Response testPostValidation(final Person person) {
if(person.getEmail() == null) {
return Response.ok(ImmutableMap.of("status", "email missing")).build();
}
return Response.ok(ImmutableMap.of("status", "ok")).build();
}
}
class Person {
#JsonProperty
private String name;
#JsonProperty
private String email;
#JsonProperty
private long phoneNo;
#JsonProperty
private String password;
public String getEmail(){
return email;
}
public Person(){};
}
In both the GET and POST method I have the QueryParams and the Person object which I would like to be validated.
I have the validation logic inside the Resource class itself, I can create a separate class and replace the if statements with
//if(email == null) {
// return Response.ok(ImmutableMap.of("status", "email missing")).build();
//}
if(!CustomValidater.validate(email, name, phone, password)) {
return Response.ok(ImmutableMap.of("status", "data missing")).build();
}
and do the same for POST as well this way the validation logic is abstracted in different class.
Is this the correct way of doing the validation or should I create custom annotation that will do this validation?
You should create custom validator, or add constraints validation to model.
Person should have properties like:
#NotNull
private String name;
#NotEmpty
private String surname;
...
And should be validated as method parameter if needed:
#Valid Person person

Restful Web Service javax.ws.rs.InternalServerErrorException: HTTP 500 Internal Server Error

Internal server Error is generic error, but in my case is bind with REST using JPA. To obtain this error I need to return List of Beans:
package resources;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceUnit;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
import model.CustomerRest;
import model.CustomerRestSchema;
//#ManagedBean
#Stateless
#Path("simplerest")
public class SimpleRESTResource {
private final static Logger logger = Logger.getLogger(SimpleRESTResource.class.getName());
//HelpExceptionMapper helpEx = new HelpExceptionMapper();
#Context
private UriInfo context;
#PersistenceUnit(unitName = "jdbc/Test")
EntityManagerFactory emf;
/**
* Default constructor.
*/
public SimpleRESTResource() {
// TODO Auto-generated constructor stub
}
private List<CustomerRestSchema> convertCustomers(List<CustomerRest> customers) {
List<CustomerRestSchema> customersSimplified = new ArrayList<>();
for(CustomerRest cust : customers) {
customersSimplified.add(new CustomerRestSchema(cust.getId(), cust.getFirstName(), cust.getLastName()));
}
return customersSimplified;
}
private List<CustomerRestSchema> getCustomers() {
List<CustomerRest> customers = null;
List<CustomerRestSchema> customersrest = null;
String result = null;
try {
EntityManager em = emf.createEntityManager();
//CustomerRest cure = (CustomerRest) emf.createEntityManager().createQuery("select u from CustomerRest u", CustomerRest.class).getResultList().get(0);
customers = (List<CustomerRest>) em.createNamedQuery("CustomerRest.findAll", CustomerRest.class).getResultList();
CustomerRest cust = customers.get(0);
result = "<greeting>Hello1 " + cust.getFirstName() + " " +cust.getLastName() + /*" " + cust.getAddressRests().get(0).getStreet() +*/ "!</greeting>";
logger.info(result);
customersrest = (new Customers(convertCustomers(customers))).getCustomers();
CustomerRestSchema custrest = customersrest.get(0);
result = "<greeting>Hello2 " + custrest.getFirstName() + " " +custrest.getLastName() + /*" " + cust.getAddressRests().get(0).getStreet() +*/ "!</greeting>";
logger.info(result);
}
catch (Exception ee) {
ee.printStackTrace();
//throw new UnsupportedOperationException();
}
return customersrest;
}
/**
* Retrieves representation of an instance of SimpleResource
* #return an instance of String
*/
#GET
#Path("custxml")
#Produces(MediaType.APPLICATION_XML)
public List<CustomerRestSchema> getXml() {
return getCustomers();
}
/**
* Retrieves representation of an instance of SimpleResource
* #return an instance of String
*/
#GET
#Path("custjson")
#Produces(MediaType.APPLICATION_JSON)
public List<CustomerRestSchema> getJson() {
return getCustomers();
}
/**
* PUT method for updating or creating an instance of SimpleResource
* #param content representation for the resource
* #return an HTTP response with content of the updated or created resource.
*/
#PUT
#Consumes(MediaType.APPLICATION_XML)
public void putXml(String content) {
}
}
If I want return String or something simple, everything is fine. If I want to return something more complex, WS fails.
The problem was in bean. If I was able properly read stack trace, I will save a lot of time:
2015-08-19T10:48:02.329+0200|Info: CDI support is enabled
2015-08-19T10:48:02.339+0200|Info: Initiating Jersey application, version 'Jersey: 1.19 02/11/2015 05:39 AM'
2015-08-19T10:48:02.820+0200|Info: Binding the EJB class resources.SimpleRESTResource to EJBManagedComponentProvider
2015-08-19T10:48:02.856+0200|Info: Loading application [HelloGlassfish] at [/HelloGlassfish]
2015-08-19T10:48:02.873+0200|Info: HelloGlassfish was successfully deployed in 3,534 milliseconds.
2015-08-19T10:52:45.657+0200|Info: Initiating Jersey application, version Jersey: 2.10.4 2014-08-08 15:09:00...
2015-08-19T10:52:46.118+0200|Info: <greeting>Hello1 Petr Hariprasad!</greeting>
2015-08-19T10:52:46.120+0200|Info: <greeting>Hello2 Petr Hariprasad!</greeting>
2015-08-19T10:52:46.175+0200|Severe: javax.ws.rs.InternalServerErrorException: HTTP 500 Internal Server Error
at org.glassfish.jersey.message.internal.AbstractCollectionJaxbProvider.writeTo(AbstractCollectionJaxbProvider.java:282)
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.invokeWriteTo(WriterInterceptorExecutor.java:263)
...
Caused by: com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
model.CustomerRestSchema **does not have a no-arg default constructor**.
this problem is related to the following location:
at model.CustomerRestSchema
at com.sun.xml.bind.v2.runtime.IllegalAnnotationsException$Builder.check(IllegalAnnotationsException.java:106)
There is a bean:
package model;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name = "customer")
public class CustomerRestSchema implements Serializable {
/***/
private static final long serialVersionUID = 1L;
private long id;
private String firstName;
private String lastName;
/** empty public constructor is important! */
public CustomerRestSchema() {
}
/** constructor */
public CustomerRestSchema(long id, String firstName, String lastName) {
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
}
public long getId() {
return id;
}
#XmlElement(name = "id")
public void setId(long id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
#XmlElement
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
#XmlElement(name = "lastName")
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
I believe, that it will be useful for somebody.

Jersey - Rest API (Json Format)

I am trying to create an Jersey application and I would like to pass the output to web browser in Json format. Below are the codes. I can only pass the data in xml format and when I change to "application/json" format, "HTTP Status 500 - Internal Server Error" came out. Any advice? thanks.
import java.net.URISyntaxException;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
#Path("/emp")
public class EmployeeService {
#GET
#Path("/get/{empID}")
#Produces({"application/json"})
public Employee getEmployee(#PathParam("empID") String empID){
Employee employee = new com.rest.employee.model.Employee();
employee.setEmpID(empID);
employee.setName("George");
employee.setEmail("george#gmail.com");
return employee;
}
}
and another java file
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlAccessorType(XmlAccessType.NONE)
#XmlRootElement(name="employee")
public class Employee {
public String empID;
public String name;
public String email;
#XmlElement(required=true)
public String getEmpID() {
return empID;
}
public void setEmpID(String empID) {
this.empID = empID;
}
#XmlElement(required=true)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#XmlElement(required=true)
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
The code looks 'nearly' fine and works for me as expected, but your Employee should implement Serializable. I can't see any other problem in there for now, so the problem is somewhere else i guess.
You said, that its not working anymore, since you changed from XML to JSON. So i reckon, that you miss a dependency for JSON. Check this ...
But in fact, the missing dependency should not result in an 500. Can it be true, that you have added a ExceptionMapper and that you throw your 500 by yourself?
You need to integrate Jersey with Jackson. Look at this tutorial:
http://examples.javacodegeeks.com/enterprise-java/rest/jersey/json-example-with-jersey-jackson/

TomEE + OpenJPA: Error creating EntityManager using container managed DataSource

I'm trying to configure an example JPA application in Eclipse, and deploy it to TomEE+. The datasource is container managed. I keep seeing the following error when attempting to create the EntityManager:
The persistence provider is attempting to use properties in the persistence.xml file to resolve the data source. A Java Database Connectivity (JDBC) driver or data source class name must be specified in the openjpa.ConnectionDriverName or javax.persistence.jdbc.driver property. The following properties are available in the configuration: "org.apache.openjpa.jdbc.conf.JDBCConfigurationImpl#414793b4".
Any idea what is wrong with this configuration?
Below is the code.
tomee.xml
<tomee>
<Resource id="jdbc/MyAppDS" type="DataSource">
JdbcDriver com.microsoft.sqlserver.jdbc.SQLServerDriver
JdbcUrl jdbc:sqlserver://localhost:1433/db_dev
UserName user
Password password
JtaManaged true
DefaultAutoCommit false
</Resource>
</tomee>
persistence.xml
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="2.0">
<persistence-unit name="Simplest" transaction-type="JTA">
<provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
<jta-data-source>jdbc/MyAppDS</jta-data-source>
<class>social.Media</class>
</persistence-unit>
</persistence>
Media.java
package social;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name = "media")
public class Media {
#Id
#Column(name = "id")
private String id;
private String description;
private String title;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
Controller.java
package social;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
#Path("/hello")
public class Controller {
#Inject private Media media;
#GET
#Produces(MediaType.TEXT_PLAIN)
public String sayHello() {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("Simplest");
EntityManager em = emf.createEntityManager(); // exception reported on this line
.
.
.
return media.getDescription();
}
}
You are using JTA-managed Entity Manager Factory, I think that instead of manual creation of EntityManagerFactory you should let application server do it for you, like this in controller:
#Path("/hello")
public class Controller {
#PersistenceContext(unitName="Simplest")
private EntityManager em;
#GET
#Produces(MediaType.TEXT_PLAIN)
public String sayHello() {
// get Media from database - replace with your own code
Media media = em.find(Media.class, "1");
return media.getDescription();
}
}

Categories

Resources