i did this tutorial http://netbeans.org/kb/docs/websvc/rest.html to create a restful webservice with my mysql db.
the basic things works fine, but now i want to extend the service functionality. how can i add additional parameters to the GET service ?
i tried this
but as a result I have all cities.
when I add the parameter countryCode links the service becomes
http://localhost:8080/Data/resources/converter.city/?
countryCode=TUR×tamp=1323114935089
This is my code
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package service;
import converter.City;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
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;
/**
*
* #author mehdi
*/
#Stateless
#Path("converter.city")
public class CityFacadeREST extends AbstractFacade<City> {
#PersistenceContext(unitName = "DataPU")
private EntityManager em;
public CityFacadeREST() {
super(City.class);
}
#POST
#Override
#Consumes({"application/xml", "application/json"})
public void create(City entity) {
super.create(entity);
}
#PUT
#Override
#Consumes({"application/xml", "application/json"})
public void edit(City entity) {
super.edit(entity);
}
#DELETE
#Path("{id}")
public void remove(#PathParam("id") Integer id) {
super.remove(super.find(id));
}
#GET
#Path("{id}")
#Produces({"application/xml", "application/json"})
public City find(#PathParam("id") Integer id) {
return super.find(id);
}
#GET
#Override
#Produces({"application/xml", "application/json"})
public List<City> findAll() {
return super.findAll();
}
#GET
#Path("{from}/{to}")
#Produces({"application/xml", "application/json"})
public List<City> findRange(#PathParam("from") Integer from, #PathParam("to") Integer to) {
return super.findRange(new int[]{from, to});
}
#GET
#Path("count")
#Produces("text/plain")
public String countREST() {
return String.valueOf(super.count());
}
#java.lang.Override
protected EntityManager getEntityManager() {
return em;
}
}
You will have to update the annotations in your Java resource class to accept the additional parameter(s). Have you looked at the annotation support for query parameters in JAX-RS?
Related
I want to read request header from SOAP incoming request in my Java code for some authorization purpose. I found few work-arounds like using SOAPHandlers and . Code as below :
`package com.cerillion.ccs.framework;
import java.util.HashSet;
import java.util.Set;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
import org.apache.log4j.Logger;
public class ApiSoapHandler implements SOAPHandler<SOAPMessageContext> {
private static final Logger logger = Logger.getLogger(ApiSoapHandler.class.getName());
#Override
public void close(MessageContext arg0) {
// TODO Auto-generated method stub
}
#Override
public boolean handleFault(SOAPMessageContext context) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean handleMessage(SOAPMessageContext context) {
logger.debug("Inside ApiSoapHandler");
try {
SOAPMessage message = context.getMessage();
SOAPHeader header = message.getSOAPHeader();
message.saveChanges();
} catch (SOAPException e) {
logger.error("Error occurred while adding credentials to SOAP header.",
e);
}
return true;
}
#Override
public Set<QName> getHeaders() {
/* QName securityTokenHeader = new QName("urn:com.intertech.secty", "token");
//new QName(“urn:com.intertech.secty”,“username”);
HashSet<QName> headers = new HashSet<QName>();
headers.add(securityTokenHeader);
return headers;*/
return null;
} }`
I ma really curious about to have some other simple alternative rather than writing entire handler just for fetching custom header tag. Is this the only way to read SOAP request header ? Any leads are really appreciated
I create a jax-ws service for get some data.I user tomcat 8.5.11.. The web service works fine and when I put the URL the WSDL shows and it previews all web methods... But it doesn't preview the output(XML) of each methods. How can I preview the output... I'm the service provider... I want to know how the output will be preview to the clients...
This is my web service class.
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package lk.slsi.webService;
import java.util.List;
import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.ws.rs.PathParam;
import lk.slsi.domain.CustomsPermit;
import lk.slsi.services.permitServices;
import org.springframework.beans.factory.annotation.Autowired;
#WebService(serviceName = "customsPermit")
public class webServiceforCustoms {
#Autowired
private permitServices permitServices;
#WebMethod
public List<CustomsPermit> getXmlbyDate(String dtIssue) {
List<CustomsPermit> permitRelease = permitServices.getPermitByDate(dtIssue);
return permitRelease;
}
#WebMethod
public CustomsPermit getXmlbyEntryNo(String SNumber) {
CustomsPermit permitRelease = permitServices.getPermitBySNumber(SNumber);
return permitRelease;
}
#WebMethod
public List<CustomsPermit> getXmlbyVATNo(String importerVAT) {
List<CustomsPermit> permitRelease = permitServices.getPermitByImporterVAT(importerVAT);
return permitRelease;
}
}
I am receiving following exception:
ClientHandlerException: A message body writer for Java type,
class com.company.testing.repo.model.Privilege,
and MIME media type,
application/octet-stream, was not found
Privilege is an ENUM class:
public enum Privilege {
READ,
WRITE;
}
Resource entry is this:
#Path("repoPrivs")
#POST
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
Response getGroups(Privilege privilege);
my client code is this:
#Override
public List<MyGroup> getGroups(Privilege privilege) {
IWebParamaterProvider provider = WebParamaterFactory.create("repo-mapping/repoPrivs", //$NON-NLS-1$
SecureAction.READ, webProxy);
provider = provider.setType(MediaType.APPLICATION_JSON);
provider = provider.setAccept(MediaType.APPLICATION_JSON);
List<MyGroup> groups = null;
groups = webProxy.post(provider, new GenericTypeFactory<MyGroup>(), MyGroup.class, privilege);
return groups;
}
Override
public final <T> List<T> post(IWebParamaterProvider provider, GenericTypeFactory<T> genericsFactory,
Class<T> clazz, Object requestEntity){
WebResource resource = ((IWebResourceProvider) provider).getWebResource();
TRACER.trace("POST: " + resource.getURI().toString()); //$NON-NLS-1$
return resource.post(genericsFactory.create(clazz), requestEntity);
}
public GenericType<List<T>> create(final Class<T> clazz) {
ParameterizedType genericType = new ParameterizedType() {
#Override
public Type[] getActualTypeArguments() {
return new Type[] { clazz };
}
#Override
public Type getOwnerType() {
return List.class;
}
#Override
public Type getRawType() {
return List.class;
}
};
return new GenericType<List<T>>(genericType) {
};
}
What is that I am missing
It is very important to provide complete minimal example so other people can help you.
Below you have Jersey 2 and Jersey 1 example and both of them uses in memory test container. Make sure to get the all the required dependencies based on the version.
Jersey 2
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import org.glassfish.jersey.jackson.JacksonFeature;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.glassfish.jersey.test.inmemory.InMemoryTestContainerFactory;
import org.glassfish.jersey.test.spi.TestContainerFactory;
import org.junit.Test;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.GenericType;
import javax.ws.rs.core.MediaType;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
import static org.junit.Assert.*;
public class JerseyVersion2Test extends JerseyTest {
#Path("hello")
public static class HelloResource {
#POST
#Produces(APPLICATION_JSON)
#Consumes(APPLICATION_JSON)
public List<MyGroup> doPost(Privilege privilege) {
List<MyGroup> myGroups = new ArrayList<>();
MyGroup myGroup = new MyGroup();
myGroup.name = "jersey";
myGroup.version = 2;
myGroups.add(myGroup);
return myGroups;
}
}
#Override
protected Application configure() {
return new ResourceConfig(HelloResource.class);
}
#Override
protected TestContainerFactory getTestContainerFactory() {
return new InMemoryTestContainerFactory();
}
#Test
public void testPost() {
List<MyGroup> myGroups = getGroups();
assertEquals(1, myGroups.size());
}
public enum Privilege {
READ,
WRITE;
}
public List<MyGroup> getGroups() {
List<MyGroup> groups = target("hello").request().
accept(MediaType.APPLICATION_JSON).
post(Entity.json(Privilege.READ)).
readEntity(new GenericTypeFactory<MyGroup>().create(MyGroup.class));
return groups;
}
#JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
public static class MyGroup {
private String name;
private double version;
}
public class GenericTypeFactory<T> {
public GenericType<List<T>> create(final Class<T> clazz) {
ParameterizedType genericType = new ParameterizedType() {
#Override
public Type[] getActualTypeArguments() {
return new Type[]{clazz};
}
#Override
public Type getOwnerType() {
return List.class;
}
#Override
public Type getRawType() {
return List.class;
}
};
return new GenericType<List<T>>(genericType) {
};
}
}
}
Jersey 1
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.sun.jersey.api.client.GenericType;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.test.framework.AppDescriptor;
import com.sun.jersey.test.framework.JerseyTest;
import com.sun.jersey.test.framework.LowLevelAppDescriptor;
import com.sun.jersey.test.framework.spi.container.TestContainerFactory;
import com.sun.jersey.test.framework.spi.container.inmemory.InMemoryTestContainerFactory;
import org.junit.Test;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
import static org.junit.Assert.assertEquals;
public class JerseyVersion1Test extends JerseyTest {
#Path("hello")
public static class HelloResource {
#POST
#Produces(APPLICATION_JSON)
#Consumes(APPLICATION_JSON)
public List<MyGroup> doPost(Privilege privilege) {
List<MyGroup> myGroups = new ArrayList<>();
MyGroup myGroup = new MyGroup();
myGroup.name = "jersey";
myGroup.version = 1.12;
myGroups.add(myGroup);
return myGroups;
}
}
#Override
protected AppDescriptor configure() {
return new LowLevelAppDescriptor.Builder(HelloResource.class).build();
}
#Override
protected TestContainerFactory getTestContainerFactory() {
return new InMemoryTestContainerFactory();
}
#Test
public void testPost() {
List<MyGroup> myGroups = getGroups();
assertEquals(1, myGroups.size());
}
public enum Privilege {
READ,
WRITE;
}
public List<MyGroup> getGroups() {
WebResource webResource = resource();
List<MyGroup> groups = webResource.path("hello").
accept(MediaType.APPLICATION_JSON).
type(MediaType.APPLICATION_JSON).
post(new GenericTypeFactory<MyGroup>().create(MyGroup.class), Privilege.READ);
return groups;
}
#JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
public static class MyGroup {
private String name;
private double version;
}
public class GenericTypeFactory<T> {
public GenericType<List<T>> create(final Class<T> clazz) {
ParameterizedType genericType = new ParameterizedType() {
#Override
public Type[] getActualTypeArguments() {
return new Type[]{clazz};
}
#Override
public Type getOwnerType() {
return List.class;
}
#Override
public Type getRawType() {
return List.class;
}
};
return new GenericType<List<T>>(genericType) {
};
}
}
}
javax.xml.bind.annotation.XmlRootElement
Java doc:
The #XmlRootElement annotation can be used with the following program
elements:
a top level class
an enum type
[...]
When a top level class or an enum type is annotated with the #XmlRootElement annotation, then its value is represented as XML element in an XML document.
in your case it is clear that Jersey unable to unmarshall the incoming JSON payload to your object, thus the exception
A message body writer for Java type, class com.company.testing.repo.model.Privilege
annotating your Enum (Privilege) with #XmlRootElement should solve the issue.
#XmlRootElement
public enum Privilege {
READ,
WRITE;
}
I have 2 restful service method getCustomerJson and getCustomerXML in a class CustomerResource where i am using jersey API for Restful Webservices. All the parameters of the 2 methods are same except one produces xml and other produces json.
When i am using the a HTTP GET request with header Content-Type="application/json" it always invokes the getCustomerXML method which returns xml.
Can someone explain me how jersey works in this kind of situation ?
import java.net.URI;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
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.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import domain.Customer;
#Path("/customers")
public class CustomerResource {
private static Map<Integer, Customer> customerDB = new ConcurrentHashMap<Integer, Customer>();
private static AtomicInteger idCounter = new AtomicInteger();
// Constructor
public CustomerResource() {
}
#GET
#Produces(MediaType.TEXT_PLAIN)
public String sayHello() {
return "Hello Kundan !!!";
}
#GET
#Path("{id}")
#Produces("application/xml")
public Customer getCustomerXML(#PathParam("id") int id, #Context HttpHeaders header) {
final Customer customer = customerDB.get(id);
List<String> contentList = header.getRequestHeader("Content-Type");
List<String> languageList = header.getRequestHeader("Accept-Language");
List<String> compressionFormatList = header.getRequestHeader("Content-Type");
if (customer == null) {
throw new WebApplicationException(Response.Status.NOT_FOUND);
}
return customer;
}
#GET
#Path("{id}")
#Produces("application/json")
public Customer getCustomerJson(#PathParam("id") int id) {
final Customer customer = customerDB.get(id);
if (customer == null) {
throw new WebApplicationException(Response.Status.NOT_FOUND);
}
return customer;
}
#POST
#Consumes("application/xml")
public Response createCustomer(Customer customer) {
customer.setId(idCounter.incrementAndGet());
customerDB.put(customer.getId(), customer);
System.out.println("Created customer " + customer.getId());
return Response.created(URI.create("/customers/" + customer.getId())).build();
}
#PUT
#Path("{id}")
#Consumes("application/xml")
public void updateCustomer(#PathParam("id") int id, Customer customer) {
Customer current = customerDB.get(id);
if (current == null)
throw new WebApplicationException(Response.Status.NOT_FOUND);
current.setFirstName(customer.getFirstName());
current.setLastName(customer.getLastName());
current.setStreet(customer.getStreet());
current.setCity(customer.getCity());
current.setState(customer.getState());
current.setZip(customer.getZip());
current.setCountry(customer.getCountry());
}
#DELETE
#Path("{id}")
public void deleteCustomer(#PathParam("id") int id) {
customerDB.remove(id);
System.out.println("Deleted !");
}
}
Use Accept: application/json. Accept tells the server what type you want back. Content-Type if for the type of data you are sending to the server, like with a POST request.
I am using this Tutorial to Create simple Java EE 7 Webservices using Netbean 7.3.1.
It run successfully, I am testing using GET, PUT, POST, DELETE. All three are working fine except POST.
I am posting this json data with ID in it, which works fine.
{"id":"2","address1":"pe3","address2":"address line1","address3":"Address line3","city":"City Name","town":"Town Name","country":"uk","postcode":"123123"}
But because my ID is auto-increment, So when I POST following json without id, it fails with bellow error
{"address1":"pe3","address2":"address line1","address3":"Address line3","city":"City Name","town":"Town Name","country":"uk","postcode":"123123"}
ERROR is
HTTP Status 400 - Bad Request
type Status report
messageBad Request
descriptionThe request sent by the client was syntactically incorrect.
GlassFish Server Open Source Edition 4.0
Can anyone explain why I need to send ID which is auto-increment type in database while send POST? Is there any work around?
code in entity Class is
.......
#Id
#Basic(optional = false)
#NotNull
#Column(name = "id")
private Integer id;
#Size(max = 45)
#Column(name = "address1")
private String address1;
#Size(max = 45)
#Column(name = "address2")
........
and AddressFacadeREST.java class looks like this.
package entities.service;
import entities.Address;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
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;
#Stateless
#Path("entities.address")
public class AddressFacadeREST extends AbstractFacade<Address> {
#PersistenceContext(unitName = "CustomerDBPU")
private EntityManager em;
public AddressFacadeREST() {
super(Address.class);
}
#POST
#Override
#Consumes({"application/xml", "application/json"})
public void create(Address entity) {
super.create(entity);
}
#PUT
#Override
#Consumes({"application/xml", "application/json"})
public void edit(Address entity) {
super.edit(entity);
}
#DELETE
#Path("{id}")
public void remove(#PathParam("id") Integer id) {
super.remove(super.find(id));
}
#GET
#Path("{id}")
#Produces({"application/xml", "application/json"})
public Address find(#PathParam("id") Integer id) {
return super.find(id);
}
#GET
#Override
#Produces({"application/xml", "application/json"})
public List<Address> findAll() {
return super.findAll();
}
#GET
#Path("{from}/{to}")
#Produces({"application/xml", "application/json"})
public List<Address> findRange(#PathParam("from") Integer from, #PathParam("to") Integer to) {
return super.findRange(new int[]{from, to});
}
#GET
#Path("count")
#Produces("text/plain")
public String countREST() {
return String.valueOf(super.count());
}
#Override
protected EntityManager getEntityManager() {
return em;
}
}
The error is generated by jax-rs service not being able to convert the json provided into an instance of the entity class. Based on how NetBeans create Entity classes and service facades, your entity class has only one not-empty constructor, and it requires the id as an input parameter. Moreover, you have a #NotNull annotation in the #Id class. If so:
Create a constructor that takes all the entity properties except the #Id property. This way, the service will be able to convert the incoming json into an instance of your entity class.
Remove the #NotNull annotation in order to avoid the JavaBeans Validator to raise an error when persisting the new entity.