RESTful web services in java - java

I am trying to pass list of Long in my resource as post data and consume type is application/xml. I am also passing two path params. It is giving me exception "media type not supported".
Please help me to solve this.
this is the code and I am having exception..
#POST
#Path("/temp/{abc}")
#Consumes(MediaType.APPLICATION_XML)
#Produces(MediaType.APPLICATION_XML)
public List<Long> createUser2(List<User> users,#PathParam("abc") String abc) {
//.................//
List<Long> listLong=new ArrayList<Long>();
listLong.add(1L);
listLong.add(2L);
System.out.println("temp called");
return listLong;
}
> org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException:
> MessageBodyWriter not found for media type=application/xml

The problem is that there's no conversion code that knows how to automatically change a Long or a List<Long> into XML. At the very least, information about what the name of the containing element must be present, and JAXB (the default supported mechanism) only applies that sort of thing at the level of a class.
The fix is to create a wrapper class with suitable JAXB annotations and return that. You might need to tweak the class to get exactly the serialization you want, but that's not hard.
#XmlRootElement(name = "userinfo")
public class UserInfo {
#XmlElement
public List<Long> values;
// JAXB really requires a no-argument constructor...
public UserInfo() {}
// Convenience constructor to make the code cleaner...
public UserInfo(List<Long> theList) {
values = theList;
}
}
#POST
#Path("/temp/{abc}")
#Consumes(MediaType.APPLICATION_XML)
#Produces(MediaType.APPLICATION_XML)
// NOTE THE CHANGE OF RESULT TYPE
public UserInfo createUser2(List<User> users,#PathParam("abc") String abc) {
//.................//
List<Long> listLong=new ArrayList<Long>();
listLong.add(1L);
listLong.add(2L);
System.out.println("temp called");
return new UserInfo(listLong); // <<<< THIS LINE CHANGED TOO
}

Related

Limiting the values of Query Params JAX-RS with CXF as implementation

I have a use case where I need to limit the values that can be passed as the query param.
#Path("/foo")
public interface Foo {
#GET
#Path("/details/id/{id}")
void getFooDetails(#PathParam("id") String id, #QueryParam("sort") String sortDirection);
}
public class FooImpl {
public void getFooDetails(String id, String sortDir) {
//Implementation
}
}
In the above example, I want to restrict the value of query param sort that can be passed via the API to ASC, DESC.
Is there any existing CXF annotation which I can use to restrict the values on a parameter? I haven't found any and so I tried the following solution.
My Approach:
#Target({ElementType.PARAMETER, ElementType.METHOD, ElementType.FIELD})
#Retention(RetentionPolicy.RUNTIME)
#Inherited
public #interface ValueSet {
String[] allowedValues();
}
The modified interface looks like this.
#Path("/foo")
public interface Foo {
#GET
#PathParam("/details/id/{id}")
void getFooDetails(#PathParam("id") String id, #QueryParam("sort") #ValueSet(allowedValues = {"ASC", "DESC"}) String sortDirection);
}
I wrote a CXF Interceptor which intercepts the API invocation. I used reflection to get a handle on FooImpl.getFooDetails params. But the problem I faced is that the interceptor looks at FooImpl.getFooDetails method and doesn't find the annotations #QueryParam on the method params since #QueryParam is on the base method and the annotation is not inherited.
Interceptor implementation:
#Provider
public class ParamValidationInterceptor extends AbstractPhaseInterceptor<Message> {
public ParamValidationInterceptor() {
super(Phase.PRE_INVOKE);
super.addBefore(someInterceptor);
}
#Override
public void handleMessage(Message message) throws Fault {
UriInfo uriInfo = new UriInfoImpl(message);
MultivaluedMap<String, String> queryParams = uriInfo.getQueryParameters();
Method methodToInvoke = (Method) message.get("org.apache.cxf.resource.method");
Parameter[] parameters = methodToInvoke.getParameters();
for (Parameter parameter : parameters) {
if (parameter.isAnnotationPresent(ValueSet.class)) {
ValueSet valueSet = parameter.getAnnotation(ValueSet.class);
QueryParam queryParam = parameter.getAnnotation(QueryParam.class);
Object invokedVal = queryParams.get(queryParam.value());
String[] allowedValues = valueSet.allowedValues();
if (!Arrays.asList(allowedValues).contains(invokedVal)) {
throw new CustomException();
}
}
}
}
}
Can anyone suggest a way forward? It would be great if anyone can suggest an alternative approach.
P.S: I am using CXF as an implementation for JAX-RS and spring is used as a container.
Update:
Like #Cássio Mazzochi Molin and #Andy McCright suggested, I will go with #Pattern annotation. But I am curious to know why the JAX-RS annotations are not inherited from the interface although the spec says they will be inherited.
Annotation inheritance
According to the section §3.6 Annotation Inheritance of the JAX-RS specification, it is recommended to always repeat annotations instead of relying on annotation inheritance.
Refer to this answer for the complete quote.
#QueryParam can be applied to different targets
Bear in mind that the #QueryParam annotation can be applied to:
Resource method parameters
Resource class fields
Resource class bean properties
Hence a manual validation can be tricky.
Use Bean Validation
For validation purposes, you should consider Bean Validation. Consider a #Pattern annotation with the allowed values:
#Pattern(regexp = "ASC|DESC")
And just annotate your resource method parameter:
#GET
#Path("foo")
public Response getFoos(#QueryParam("sort")
#Pattern(regexp = "ASC|DESC") String sortDirection) {
...
}
If you prefer case insensitive values, use:
#Pattern(regexp = "ASC|DESC", flags = Pattern.Flag.CASE_INSENSITIVE)
If the given value is invalid, a ConstraintViolationException will be thrown. To handle such exception and return a customized response, you can use an ExceptionMapper:
#Provider
public class ConstraintViolationExceptionMapper
implements ExceptionMapper<ConstraintViolationException> {
#Override
public Response toResponse(ConstraintViolationException exception) {
...
}
}
Perhaps it is just a typo, but CXF may not be recognizing the getFooDetails method (on the interface) because it is annotated with #PathParam instead of #Path.
Instead of using your ValueSet approach, I used BeanValidation, but the following code works for me.
Foo.java
#Path("/foo")
public interface Foo {
#GET
#Path("/details/id/{id}")
Response getFooDetails(
#PathParam("id") #Pattern(regexp="[0-9]*") String id,
#QueryParam("sort") #Pattern(regexp = "ASC|DESC") String sortDirection);
}
FooImpl.java
public class FooImpl implements Foo {
#Override
public Response getFooDetails(String id, String sortDirection) {
Integer idInt = Integer.parseInt(id);
if ("ASC".equals(sortDirection) || sortDirection == null) {
...
} else if ("DESC".equals(sortDirection)) {
...
}
return ...;
}
I've got this working on WebSphere Liberty 17.0.0.2 which is based on CXF 3.1.11.
Hope this helps,
Andy

jersey - use custom class in URI of resource

I have a custom data class:
public static class Data {
...
}
I want to use this class in the URI of a resource in Jersey. For example:
#Path("test")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public class ResourceTest {
#GET
#Path("/data-{data}")
public Response get(#PathParam("data") final Data data) {
...
}
}
Is this possible? I guess I need to inject some kind of converter, which converts the textual representation of a Data to a Data instance. I have been looking in the documentation, but haven't found something useful so far.
Ofcourse, I can change this to:
#Path("test")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public class ResourceTest {
#GET
#Path("/data-{data}")
public Response get(#PathParam("data") final String input) {
final Data data = convert(input);
...
}
}
But I would rather do the conversion elsewhere/automagically wrt. the resource.
From the docs:
The type of the annotated parameter, field or property must either:
...
Have a constructor that accepts a single String argument.
Have a static method named valueOf or fromString that accepts a single String argument (see, for example, Integer.valueOf(String)).
Have a registered implementation of ParamConverterProvider JAX-RS extension SPI that returns a ParamConverter instance capable of a "from string" conversion for the type.
So if you provide a constructor Data(String) you should be fine.

Custom response on bad request using spring RestController

I have the following controller. I am using Spring to create Restful APIs.
#RestController
public class UserController extends RestControlValidator {
#RequestMapping(value = "/user/", method = RequestMethod.POST, headers = "Accept=application/json", consumes = "application/json", produces = MediaType.APPLICATION_JSON_VALUE)
public #ResponseBody List newUser(#RequestBody #Valid UserInput input,BindingResult result)
{Some code}
}
The UserInput class looks like this:
public class UserInput{
#NotEmpty
private String emailId;
#NotEmpty
private String fName;
private String lName;
private int sex;
//getters and setters
Now when I try and access /user/ with data {"sex":"Male"}, I get the following response:
I want the response in case of such a request to be:
{"errors":{"sex":"The value must be an integer"}}
Is there any way of customising BAD REQUEST responses in Spring?
Considering the current scenario the most ideal solution would be to alter the behavior of HandlerMethodArgumentResolve as the json to pojo constructed by #RequestBody fails because we dont get a chance to check the wrong data and this check can very well be done in the custom message converter
A. first we would need to create LanguageMessageConverter as follows
public class LanguageMessageConverter extends
AbstractHttpMessageConverter<Language> {
private Gson gson = new Gson();
public LanguageMessageConverter() {
super(new MediaType("application", "json", Charset.forName("UTF-8")));
}
#Override
protected boolean supports(Class<?> clazz) {
return Language.class.equals(clazz);
}
Map<String, String> mp = new HashMap<>();
#Override
protected Language readInternal(Class<? extends Language> clazz,
HttpInputMessage httpInputMessage) throws IOException,
HttpMessageNotReadableException {
Map langmp = gson.fromJson(
convertStreamToString(httpInputMessage.getBody()), Map.class);
for (Field field : clazz.getDeclaredFields()) {
if (!langmp.get(field.getName()).getClass().getCanonicalName().equals(field.getType().getCanonicalName())) {
if (field.getType().getCanonicalName().equals("java.lang.Integer")||field.getType().getCanonicalName().toString().equals("int")) {
langmp.put(field.getName(), "0");
} else if (field.getType().equals("java.lang.String")) {
//TODO COde needs to be improved here because this check is not efficient
langmp.put(field.getName(), "wrong");
}
}
}
Language lang = gson.fromJson(gson.toJson(langmp), clazz);
return lang;
}
we need to set the media type new MediaType("application", "json", Charset.forName("UTF-8")) which will make sure this class intervenes the mentioned MIME type
Considering we need to manipulate the result I found it best to convert it to map langmp (There are better JSON Parsers which can be used)
Since we need to to understand the existing type I used reflection api to get the fields via getDeclaredFields()
Using the above made the logical check using the datatype to understand if the type is incorrect for eg if the field datatype is int and if it is found as String then corresponding map value will be substituted
once that is done the map will hold the updated values where in if the data was wrong a default value would be set eg if the int var is set to 0 since the originating json had a String in it.
Once that is done the updated map is converted to the concerned class.
B. Secondly we need to register the custom MessageConverter in the dispatcher xml i.e. LanguageMessageConverter
<mvc:annotation-driven >
<mvc:message-converters register-defaults="true">
<bean class="com.comp.org.controller.LanguageMessageConverter" />
</mvc:message-converters>
</mvc:annotation-driven>
register-defaults="true" is very important since we are adding Custom MessageConverter but we also need the other existing converters working along with the one we have added
LanguageMessageConverter needs to be registered here.
C. Considering the concerned pojo is populated with the necessary details it would reach our controller post processing in the custom converter now we would add the manual validation eg. if the int variable has 0 the necessary error json should be returned
As per your request even if the json consists of the wrong data the custom message converter should process it and accordingly in the controller we can validate the condition mentioned.
The code definitely can be improved further. Kindly let me know if this solution fulfilled your requirement or any part of the code requires further elaboration and hopefully addressed your concern.
I had the same issue, than I solved that way:
Create an Object called Error, like that (don't forget to implement Serializable...):
private String fieldName;
private String errorCode;
private String defaultMessage;
public Error() {
}
public Error(String fieldName, String errorCode, String defaultMessage) {
this.fieldName = fieldName;
this.errorCode = errorCode;
this.defaultMessage = defaultMessage;
}
/* getters, setters */
Inside the #RestController method you ave to call inputValidator.validate() method (if you didn't create an Object Validator for your UserInput then we're really don't speaking the same language...)
// validating the userInput
userInputValidator.validate(userInput, bindingResult);
if (bindingResult.hasErrors()) {
List<Error> errors = new ArrayList<>(bindingResult.getErrorCount());
for (FieldError fieldWithError : bindingResult.getFieldErrors()) {
errors.add(new Error(fieldWithError.getField(), fieldWithError.getCode(), fieldWithError.getDefaultMessage()));
}
return errors;
}
// in case of success:
return null;
Finally you'll have to translate the JSON object to your client side. You'll have two kind of objects:
3.1. null (undefined depending on the language you're using)
3.2. A JSON object like that:
[
{
"fieldName": "name",
"errorCode": "user.input.name.in.blank",
"defaultMessage": "Insert a valid name!"
},
{
"fieldName": "firstPhone",
"errorCode": "user.input.first.phone.blank",
"defaultMessage": "Insert a valid first phone!"
}
]

REST service that accepts and returns object. How to write client?

I have declared two REST web services. One which simply returns a object. And other which accepts an object and returns another object.
POJO Order.java is used.
#XmlRootElement
public class Order {
private String id;
private String description;
public Order() {
}
#XmlElement
public String getId() {
return id;
}
#XmlElement
public String getDescription() {
return description;
}
// Other setters and methods
}
Webservice is defined as
#Path("/orders")
public class OrdersService {
// Return the list of orders for applications with json or xml formats
#Path("/oneOrder")
#GET
#Produces({MediaType.APPLICATION_JSON})
public Order getOrder_json() {
System.out.println("inside getOrder_json");
Order o1 = OrderDao.instance.getOrderFromId("1");
System.out.println("about to return one order");
return o1;
}
#Path("/writeAndIncrementOrder")
#GET
#Produces({MediaType.APPLICATION_JSON})
#Consumes({MediaType.APPLICATION_JSON})
public Order writeAndIncrementOrder(Order input) {
System.out.println("inside writeAndIncrementOrder");
Order o1 = new Order();
o1.setId(input.getId()+1000);
o1.setDescription(input.getDescription()+"10000");
System.out.println("about to return one order");
return o1;
}
I could write client code to call the web service that does not accept anything but returns object. Client code is as follows
import java.net.URI;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Invocation.Builder;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import org.glassfish.jersey.client.ClientConfig;
public class Test {
public static void main(String[] args) {
WebTarget target2 = client.target(getBaseURI()).path("rest").path("orders");
String o2 = target2.path("oneOrder").request().accept(MediaType.APPLICATION_JSON).get(String.class);
System.out.println(o2);
}
private static URI getBaseURI() {
return UriBuilder.fromUri("http://localhost:8090/FirstRESTProject").build();
}
But I do not understand how to call other service which accepts as well as returns object.
I tried different solutions given on internet. But nothing worked for me. Some solution works only for sending object and some works only for accepting. But none worked for doing both in one call.
EDIT
As suggested in below answer I registered JacksonJaxbJsonProvider.class But auto-conversion into Order object is not happening.
String o2 = target2.path("oneOrder").request().accept(MediaType.APPLICATION_JSON).get(String.class);
client.register(JacksonJaxbJsonProvider.class);
Order o4 = target2.path("oneOrder").request().accept(MediaType.APPLICATION_JSON).get(Order.class);
In above program I successfully get string as {"id":"1","description":"This is the 1st order"} But getting direct object throws error
MessageBodyReader not found for media type=application/json, type=class shopping.cart.om.Order, genericType=class shopping.cart.om.Order.
If you take a little bit of time to understand the WebTarget API, as well as the different types returned from calls to WebTarget's method, you should get a better understanding of how to make calls. It may be a little confusing, as almost all the example use method chaining, as it's a very convenient way, but doing this, you miss all the actual classes involved in create and sending the request. Let break it down a bit
WebTarget target = client.target(getBaseURI()).path("rest").path("orders");
WebTarget.path() simply returns the WebTarget. Nothing interesting there.
target.path("oneOrder").request().accept(MediaType.APPLICATION_JSON).get(String.class)
WebTarget.request() returns Invocation.Builder
Invocation.Builder.accept(..) returns Invocation.Builder
Invocation.Builder.get() calls its super class's SyncInvoker.get(), which makes the actual request, and returns a type, based on the argument we provide to get(Class returnType)
What you're doing with get(String.class) is saying that the response stream should be deserialized into a Sting type response. This is not a problem, as JSON is inherently just a String. But if you want to unmarshal it to a POJO, then you need to have a MessageBodyReader that knows how to unmarshal JSON to your POJO type. Jackson provides a MessageBodyReader in it's jackson-jaxrs-json-provider dependency
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>2.4.0</version>
</dependency>
Most implementations will provider a wrapper for this module, like jersey-media-json-jackson for Jersey or resteasy-jackson-provider for Resteasy. But they are still using the underlying jackson-jaxrs-json-provider.
That being said, once you have that module on the classpath, is should be automatically registered, so the MessageBodyReader will be available. If not you can register it explicitly with the client, like client.register(JacksonJaxbJsonProvider.class). Once you have the Jackson support configured, then you can simply do something like
MyPojo myPojo = client.target(..).path(...).request().accept(..).get(MyPojo.class);
As for posting/sending data, you can again look at the different Invocation.Builder methods. For instance
Invocation.Builder builder = target.request();
If we want to post, look at the different post methods available. We can use
Response post(Entity<?> entity) - Our request might look something like
Response response = builder.post(Entity.json(myPojo));
You'll notice the Entity. All the post methods accept an Entity, and this is how the request will know what type the entity body should be, and the client will invoke the approriate MessageBodyWriter as well as set the appropriate header
<T> T post(Entity<?> entity, Class<T> responseType) - There's another overload, where we can specify the type to unmarshal into, instead of getting back a Response. We could do
MyPojo myPojo = builder.post(Entity.json(myPojo), MyPojo.class)
Note that with Response, we call its readEntity(Class pojoType) method to read from the Response, the entity body. The advantage of this, is that the Response object comes with a lot of useful information we can use, like headers and such. Personally, I always get the Response
Response response = builder.get();
MyPojo pojo = response.readEntity(MyPojo.class);
As an aside, for your particular code you are showing, you most likely want to make it a #POST method. Remember #GET is mainly for retrieving data, PUT for updating, and POST for creating. That is a good rule of thumb to stick to, when first starting out. So you might change the method to
#Path("orders")
public class OrdersResource {
#POST
#Produces(MediaType.APPLICATION_JSON)
#Consumes({MediaType.APPLICATION_JSON})
public Response createOrder(#Context UriInfo uriInfo, Order input) {
Order order = orderService.createOrder(input);
URI uri = uriInfo.getAbsolutePathBuilder().path(order.getId()).build();
return Response.create(uri).entity(order).build();
}
}
Then you can do
WebTarget target = client.target(BASE).path("orders");
Response response = target.request().accept(...).post(Entity.json(order));
Order order = response.readEntity(Order.class);
You should use POST or PUT instead GET
try this code
final Client client = new Client();
final Order input = new Order();
input.setId("1");
input.setDescription("description");
final Order output = client.resource(
"http://localhost:8080/orders/writeAndIncrementOrder").
header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON).
entity(input).post(Order.class);

Using Java-generics template type in RESTful Response object via GenericEntity<List<T>>

I have a generic JAX-RS resource class and I have defined a generic findAll method
public abstract class GenericDataResource<T extends GenericModel> {
#GET
#Produces(MediaType.APPLICATION_JSON)
public Response findAll() {
Query query = em.createNamedQuery(modelClass.getSimpleName()+".findAll");
List<T> list = query.getResultList();
return Response.ok(new GenericEntity<List<T>>(list) {}).build();
}
}
and User class:
public class User extends GenericModel {
...
}
And here is example subclass definition:
#Path("users")
public class UserResource extends GenericDataResource<User> {
public UserResource() {
super(User.class);
}
}
I get below Exception:
com.sun.jersey.api.MessageException: A message body writer for Java class
java.util.Vector, and Java type java.util.List<T>,
and MIME media type application/json was not found exception.
If I replace T with a defined class such as User like so:
GenericEntity<List<User>>(list)
then it works fine.
Any idea as to how I can make it work with generic T?
Once the source code is compiled, the (anonymous) class created by the line:
new GenericEntity<List<T>>(list) {}
uses a type variable to refer to its parent. Since type variables have no value at runtime, you can't use generics like this. You are forced to pass a so-called type token from the calling site. This is an example which requires the token to be passed from the caller of findAll(), but you could require one in the constructor and save it in an instance variable as well:
public abstract class GenericDataResource<T extends GenericModel> {
public Response findAll(GenericEntity<List<T>> token) {
Query query = em.createNamedQuery(modelClass.getSimpleName() + ".findAll");
List<T> list = query.getResultList();
return Response.ok(token).build();
}
}
The caller will send a token like
new GenericEntity<List<User>>() {}
If you only use non-parameterized subclasses, findAll() may take advantage of reflection to build the token (untested, hope you get the idea):
#GET
#Produces(MediaType.APPLICATION_JSON)
public Response findAll() {
Query query = em.createNamedQuery(modelClass.getSimpleName()+".findAll");
List<T> list = query.getResultList();
return Response.ok(new GenericEntity(list, getType())).build();
}
You have to implement getType() to return the desired type. It will be a subclass of ParameterizedType capable of denoting the type List<DAO<User>>
In addition to the answers, to read the Response object back on the client :
List<MyObject> list = response.readEntity(new GenericType<List<MyObject>>(){}));
Response object gets returned to client in response to request sent to a server. The Response class has Response.ResponseBuilder inner class that collects each properties set to its field of type Response.ResponseBuilder. Response.ResponseBuilder applies the Builder design pattern to construct Response Object.
The build() method is responsible to connect the chain of Response.ResponseBuilder objects formed in the course of build.
E.g.
Response.status(200);
status method return Response.ResponseBuilder after assigning STATUS
Response.status(200).entity( AnyObj );
entity object assigns the entity( the payload returned back) of type
Response.ResponseBuilder and gets assigned to the Response's instance varible of. After that, status also assigns the status and returns Response.ResponseBuilder instance. The builder connects them at time of build() method call.
Response.status(200).entity( obj ).build();
Finally, the build method constructs complete(with properties set forth) Response.
Now comes the question of GenericEntity object. It Represents a response entity of a generic type T.
For Instance,
GenericEntity> obj = new GenericEntity>(lst) {};
Response.status(200).entity( obj ).build();
obj is type of List as given above. entity method accepts Object type which is generic. In case, the need of specific type arises, you got to pass it as argument of GenericEntity type by which at runtime it's casted to object of Specific type.
Practical Use
Wanted for my Jersey Framework to respond JSON of Array type which was List object in my Java model back to client as part of Response object.
Therefore,
new GenericEntity> --- casts the object/payload to List type
new GenericEntity --- runtime type becomes String
Resource on Webservice Side
public Response findAllFruits(#QueryParam("frtID") String frtID ) {
List<String> lst = new ArrayList<String>();
lst.add("Banana");
lst.add("Apple");
GenericEntity<List<String>> obj = new GenericEntity<List<String>>(lst) {};
return Response.status(200).entity( obj ).build();
}
Output
Response sent back to client.
[
"Banana",
"Apple"
]
How to Read Response Entity
List<CustomType> myObj= response.readEntity(new GenericType<List<CustomType>>() {});
To solve it a made a method to return a GenericEntity and then a invoke it from my generic class, some thing like below:
#XmlRootElement
public abstract class AbstractRest<T extends IEntity> {
private Long id;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
}
public abstract class SmartWebServiceNEW<R extends AbstractRest<T>> {
#GET
#Produces({MediaType.APPLICATION_XML})
public Response findAll() {
List<T> lista = getDelegate().findAll();
if (lista == null || lista.isEmpty()) {
return Response.status(Response.Status.NO_CONTENT).build();
}
List<R> retorno = new ArrayList<R>();
for (T it : lista) {
retorno.add(toRest(it));
}
GenericEntity entity = listToGenericEntity(retorno);
return Response.ok(entity).build();
}
protected abstract GenericEntity listToGenericEntity(List<R> restList);
}
#Path("/something")
#RequestScoped
public class MyEntityResource extends SmartWebServiceNEW<MyEntityExtendingAbstractRest> {
#Override
protected GenericEntity listToGenericEntity(List<MyEntityExtendingAbstractRest> restList) {
return new GenericEntity<List<MyEntityExtendingAbstractRest>>(restList) {
};
}
}

Categories

Resources