How can I get XML and/or URL (String) in JAX-RS service?
For example in GET method URL
#GET
#Produces("application/xml; charset=UTF-8")
public JaxrsPriceWrapper getPrice(#QueryParam("firstId"), #QueryParam("materialId"),...) {
//here I would like to get whole URL
}
and in POST method XML
#POST
public JaxrsOrderWrapper insertOrder(OrderJaxrsVO jaxrsVO) {
//here the XML
}
This works for me using Jersey. Add a variable;
#Context private UriInfo uriInfo;
.. to your resource class. This will be made available to the resource methods. You can then call
uriInfo.getRequestURI().
Example;
import javax.ws.rs.GET;
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;
#Path("/jerseytest")
public class Server
{
#Context private UriInfo uriInfo;
#GET
#Produces(MediaType.APPLICATION_XML)
public String get()
{
System.out.println("jerseytest called: URI = " + uriInfo.getRequestUri());
return "<response>hello world</response>";
}
}
Edit:
You probably need to annotate your POST method with #Consumes(MediaType.APPLICATION_XML) to get the data posted.
Related
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 javax.ws.rs.core.Response;
import java.util.List;
public interface EmployeeServ {
#POST
#Path("/v1/employees/xdata/{id}")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
Response updateReport(List<String> request, String id);
}
So this method doesn't need a body because all the annotations are doing the needful.
Is there anyway I can make this method static/default?
Nope.
Methods without any body are abstract. All methods of an interface without any body are public abstract implicitly.
static and default methods can not be abstract therefore you can not make your method static or default.
I'm struggling on implementing a generic abstract jaxrs service without duplicating several jaxrs annotations.
So, for example, here is my service and entity structure:
AbstractEntity.java
import javax.xml.bind.annotation.XmlElement;
public abstract class AbstractEntity {
#XmlElement
private String name;
public String getName() {
return name;
}
}
AbstractService.java
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 javax.ws.rs.core.Response;
public class AbstractService<T extends AbstractEntity> {
#POST
#Consumes(MediaType.APPLICATION_XML)
#Produces(MediaType.TEXT_PLAIN)
#Path("/details")
public Response getEntityDetails(final T entity) {
// just return the name of this entity
return Response.ok(entity.getName()).build();
}
}
The implementation is like:
Car.java
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
public class Car extends AbstractEntity {
#XmlElement
private String brand;
public String getBrand() {
return brand;
}
}
CarService.java
import javax.ws.rs.Path;
#Path("/cars")
public class CarService extends AbstractService<Car> {
// should provide the super getEntityDetails method with a Car entity
}
Now i want to POST my car entity to /cars/details to get the details (return the name "A5" which is implemented in the abstract service):
POST /cars/details
<car>
<brand>Audi</brand>
<name>A5</name>
</car>
Unfortunately, when I post it to my service, it says:
JAXRSUtils W .No message body reader found for request class : AbstractEntity, ContentType : application/xml.
WebApplicatio W WebApplicationException has been caught : no cause is available
I can correct it, if I implement my CarService as follows:
CarService.java
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 javax.ws.rs.core.Response;
#Path("/cars")
public class CarService extends AbstractService<Car> {
#POST
#Consumes(MediaType.APPLICATION_XML)
#Produces(MediaType.TEXT_PLAIN)
#Path("/details")
#Override
public Response getEntityDetails(final Car entity) {
return super.getEntityDetails(entity);
}
}
And removing all jaxrs annotations from the abstract service:
AbstractService.java
import javax.ws.rs.core.Response;
public class AbstractService<T extends AbstractEntity> {
public Response getEntityDetails(final T entity) {
// just return the name of this entity
return Response.ok(entity.getName()).build();
}
}
The point is, that I have about 60 of these CarService implementations and I don't want to repeat the getDetails method with all it's jaxrs annotation in each service, because it's always the same (the same boilerplate).
Any ideas or solutions on that?
potentially you may want to also have a look at more resource-oriented rest libraries to complement your JAX-RS codebase. They can do exactly that (path mappings, sorting, filtering, paging, etc.) without an annotation or abstract base class hell. crnk.io + jsonapi, graphql, falcor are such libraries. (disclaimer: I contribute to the first one)
I wanted to extend or customize my existing rest apis. In my rest the Service calls the Handler which is supposed to contain business logic (as a product) and I need a way to extend or customize this (per client customization). Please advise how to go about doing this. Attached is a simple hello world setup I have, it would be great it a hook into this 'DefaultGreetingsHandler.greetUser' can be shown.
package com.myapi.greetings.rest;
import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
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.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import com.myapi.greetings.handler.GreetingsHandler;
import com.myapi.greetings.model.Greeting;
#Path("/greetings")
public class GreetingsService {
#Inject
GreetingsHandler handler;
#GET
#Path("/{name}")
public Response getCustomMessage(#PathParam("name") String name) {
String output = handler.greetUser(name);
return Response.status(200).entity(output).build();
}
}
I need a hook in the Handler.greetUser to be able to customize per client
package com.myapi.greetings.handler;
import javax.inject.Inject;
import com.myapi.greetings.dao.GreetingsDao;
public class DefaultGreetingsHandler implements GreetingsHandler {
#Inject
GreetingsDao dao;
#Override
public String greetUser(String name) {
return dao.getGreeting() + name;
}
}
Its a simple maven based rest project in java. Please refer to following link for the complete setup zip file.
https://1drv.ms/u/s!AulFHVWnSJeFaqIB0JHKzo95DbU
Appreciate the help.
Create a New Class MyApplicationBinder
import org.glassfish.hk2.utilities.binding.AbstractBinder;
public class MyApplicationBinder extends AbstractBinder {
#Override
protected void configure() {
bind(GreetingsHandler.class).to(GreetingsHandler.class);
}
}
and then Register it in the main application class
#ApplicationPath("webapi")
public class MyApp extends ResourceConfig{
public MyApp() {
register(new MyApplicationBinder());
packages(true, "com.myapi.greetings.rest");
}
}
This should make your application work .
I am working on a simple RESTful Api using Jersey 2.10 and running on Tomcat 8.
this is my Application class :
package com.manager.api.application;
import javax.ws.rs.ApplicationPath;
import org.glassfish.jersey.server.ResourceConfig;
#ApplicationPath ("api")
public class Application extends ResourceConfig {
public Application () {
packages ("com.manager.api.resources");
}
}
My Resources package contains :
an interface : Resources.java
package com.manager.api.resources;
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.Produces;
import javax.ws.rs.core.MediaType;
public interface Resources {
#GET
#Produces (MediaType.APPLICATION_JSON)
public JsonObject getList ();
#GET
#Path ("value=/{id}")
#Produces (MediaType.APPLICATION_JSON)
public JsonObject get (String id);
#POST
#Path ("value=/{data}")
#Consumes (MediaType.APPLICATION_JSON)
public void post (JsonObject data);
#PUT
#Path ("value=/{data}")
#Consumes (MediaType.APPLICATION_JSON)
public void put (JsonObject data);
#DELETE
#Path ("value=/{id}")
public void delete (String id);
}
An abstract class : ResourcesImpl.java which implements the Resources interface
package com.manager.api.resources;
public abstract class ResourcesImpl implements Resources {
}
And finally a resource class which extends ResourcesImpl.java : UserResources.java
package com.manager.api.resources;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import com.manager.api.dao.UserDao;
#Path ("value=/users")
public class UserResources extends ResourcesImpl {
private UserDao user = new UserDao ();
#GET
#Path ("value=/test")
#Produces (MediaType.TEXT_PLAIN)
public String Test () {
return "Test";
}
#Override
public JsonObject getList () {
return user.getList ();
}
#Override
public JsonObject get (String id) {
return user.get (id);
}
#Override
public void post (JsonObject data) {
user.post (data);
}
#Override
public void put (JsonObject data) {
user.put (data);
}
#Override
public void delete(String id) {
user.delete (id);
}
}
and my web.xml contains only a <display-name> Tag :
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
id="WebApp_ID" version="3.1">
<display-name>manager-api</display-name>
</web-app>
I run my project successfully but I get 2 problems :
The following warnings have been detected: WARNING: A HTTP GET method, public JsonObject com.manager.api.resources.UserResources.get(java.lang.String), should not consume any entity. : Which I find strange since I put #Produces (MediaType.APPLICATION_JSON) and didn't put a #Consumes for this method.
Finally the big problem is the 404 error I get when I type : http://localhost:8080/manager-api/api/users/test when it should print Test as text.
Do you have any idea about what is the reason behind those 2 errors ? Thank you.
Make sure your pom.xml has servlet 3.0 and not 2.0. Also try giving an absolute path instead of a relative one in your #ApplicationPath annotation (such as "/api"). Also maybe your package declaration is incorrect for the resourceconfig?
Refer to this if you have more troubles:
How to set up JAX-RS Application using annotations only (no web.xml)?
I am trying to create a simple web service which outputs using json, but am not getting the desired Json output.
POJO:
package com.rest.resource;
import java.io.Serializable;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class Track implements Serializable
{
#XmlElement
String singer = "ABC";
#XmlElement
String title = "XYZ";
}
Service:
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.xml.bind.JAXBException;
import com.rest.resource.Track;
#Path("/json/metallica")
public class JSONService
{
#POST
#Path("/post")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public Track createTrackInJSON(final Track track)
{
return track;
}
#GET
#Path("/get")
#Produces(MediaType.APPLICATION_JSON)
public Response getTrackInJSON() throws JAXBException
{
final Track track = new Track();
return Response.status(201).entity(track).build();
}
}
On /get I get
{"singer":"ABC","title":"XYZ"}
but I want "track": {"singer":"ABC","title":"XYZ"}
I am unable yo print the root element.
I tried using a CustomJAXBContextResolver class but did not work for me? Can anyone give an example of the same?
If you want to use the ContextResolver, you'd need to use the JSONConfiguration and switch the JSON Notation. You could do that by adding a class like this:
#Provider
public class MyJAXBContextProvider implements ContextResolver<JAXBContext> {
private JSONJAXBContext trackCtx;
public MyJAXBContextProvider() throws JAXBException {
trackCtx = new JSONJAXBContext(JSONConfiguration.mappedJettison().build(), Track.class);
}
public JAXBContext getContext(Class<?> type) {
if(type == Track.class) {
return trackCtx;
}
return null;
}
}
Adding that class produced this for me:
{"track":{"singer":"ABC","title":"XYZ"}}
For more info check out the Jersey Docs
You'd have to wrap Track with another object:
public class TrackWrapper {
Track track;
TrackWrapper(Track track) {
this.track=track;
}
}
and return an instance of TrackWrapper,
#GET
#Path("/get")
#Produces(MediaType.APPLICATION_JSON)
public Response getTrackInJSON() throws JAXBException
{
final TrackWrapper trackWrapper = new TrackWrapper(new Track());
return Response.status(201).entity(trackWrapper).build();
}
}
and just in case, if you're gonna use JSON only you don't need the JAXB annotations.