I'm trying to use Errai rest capabilities in my GWT app,
I took a look at the following guide:
http://errai-blog.blogspot.it/2011/10/jax-rs-in-gwt-with-errai.html
In particular, it says:
We simply put this interface somewhere in our client packages (e.g.
client.shared) where the GWT compiler can find it. To create a request
all that needs to be done is to invoke RestClient.create()
I think there's a plot hole here, how is Errai able to know how serialize/deserialize model classes ?
Can you help understanfing this ?
thanks
According to RestClient Class's create() method
public static <T, R> T create(final Class<T> remoteService, final RemoteCallback<R> callback, Integer... successCodes) {
return create(remoteService, null, callback, null, successCodes);
}
In example which you've provided; when using create() method Errai gets the CustomerService Class as remoteService, After many operations;
Errai parses and implements this CustomerService Interface with using their errai-codegen library which uses Java Reflection API.
When parsing simply;
First it looks for JAX-RS annotated methods and defines them as
JaxrsResourceMethod
Then it looks into parameters of that method if there is any parameter that annontated with JAX-RS annotations.
If it finds annontated parameters in JaxrsResourceMethod, it keeps that parameter with it's annotation type
If it finds not annontated parameter in JaxrsResourceMethod it defines as a entityParameter
Errai holds these annotated parameter and entityParameters in JaxrsResourceMethodParameters by their method. When building request it uses parameters by their rule.
Let me explain these rules with using an example you've provided.
Customer customer = new Customer("new name", "new last name", "new postal code");
RestClient.create(CustomerService.class, callback).updateCustomer(240193, customer);
Errai will create url like
example.com/cusomers/240193
Because #PathParam("id") annotation rule is adding parameter to the url and according to Errai's entityParameter rule customer will be marshalled when sending data with PUT.
#PUT
#Path("/{id}")
#Consumes("application/json")
#Produces("application/json")
public Customer updateCustomer(#PathParam("id") long id, Customer customer); //- See more at: http://errai-blog.blogspot.com.tr/2011/10/jax-rs-in-gwt-with-errai.html#sthash.2GTQtIg8.dpuf
One more additional note if you check here there is an exception in setEntityParameter method;
Only one non-annotated entity parameter allowed per method:
This means you cant define methods with more than 1 non-annotated parameter in Class which you sent in Errai.
Related
I am trying to solve some vulnerabilities issues, and I have one that I couldn't solve it, I tried to add #Valid annotation in sync method but same error, this is the description from fortify:
The framework binder used for binding the HTTP request parameters to
the model class has not been explicitly configured to allow, or
disallow certain attributes.
To ease development and increase productivity, most modern frameworks
allow an object to be automatically instantiated and populated with
the HTTP request parameters whose names match an attribute of the
class to be bound. Automatic instantiation and population of objects
speeds up development, but can lead to serious problems if implemented
without caution. Any attribute in the bound classes, or nested
classes, will be automatically bound to the HTTP request parameters.
Therefore, malicious users will be able to assign a value to any
attribute in bound or nested classes, even if they are not exposed to
the client through web forms or API contracts.
The error I am getting in this line:
public ResponseClass sync(#BeanParam MyClassRequest request) throws
Exception {
MyClassResource.java
#Api(tags = "Relay")
#Stateless
public class MyClassResource extends AbstractService<MyClassRequest, ResponseClass> {
#EJB
private MyClassService myClassService;
#POST
#Path("/api/v1/service")
#Produces({"application/json"})
#ApiOperation(value = "Processes Conn",
response = ResponseClass.class, responseContainer = "ResponseClass", hidden = true)
#Override
public ResponseClass sync(#BeanParam MyClassRequest request) throws Exception {
myClassService.processFeed(request);
return new RelayResponse(HttpStatuses.ACCEPTED.getStatus());
}
MyClassRequest.java
In this file I have tried #FormParam("ccc") but same
public class MyClassRequest extends RelayRequest {
public MyClassRequest() {
super.setMessageType("not required");
}
private String myData;
private String conneRid;
private String connectionCreatedDate;
If someone could give some hint that how I can solve it, I will really appreciate it.
Do you expect all fields to be present in request? You are using #Valid annotation but there are no validation annotations in MyClassRequest model. Try to add some validation annotations like #JsonIgnore for non mandatory fields. Or #JsonInclude on class. If this does not help, may be also try explicitly adding #JsonProperty on each field.
I have a web application where the user client calls a web service (lets call it svc1), which in turn calls another web service (svc2) to get some data.
The UI sends an input DTO to svc1 which converts it to input MODEL for svc2, svc2 then returns output MODEL to svc1 which is converted to output DTO to be sent to the browser.
The svc1 code is implemented as below:
public OutputDto svc1(InputDto dto1){
InputModel model1 = inputAssembler.convertViewToModel(dto1);
Output model2 = svc2.call(model1);
return outputAssembler.convertModelToView(model2);
}
I want to know how to implement a design which will take care of calling the convertViewToModel() and convertModelToView() everytime the svc1 method is executed. I have the design in such a way that every Model/View pair has an Assembler (Mapper) class that has got two methods called convertViewToModel() and convertModelToView()
interface Assembler<S,T>{
S convertModelToView(T t);
T convertViewToModel(S s);
}
class InputAssembler<InputDto, InputModel> implements Assembler{
....
}
I am thinking about AOP, but I think I am missing something.
You could try using a simple mapper dependency like MapStruct , which have functions that automatically map between two Java Beans.This is particularly useful for cases when there is a lot of boiler plate code needed to convert one DTO to model and vice-versa.
The added advantage is that Mapstruct has inbuilt support for spring and Dependency Injection.
The dependency that is needed is :
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-jdk8</artifactId>
<version>1.3.0.Beta2</version>
</dependency>
Also take care to include the mapstruct-processor plugin in pom.
Then you can provide an interface like (not accurate as i don't know your dto class and fields) :
#Mapper public interface OutputMapper {
#Mappings({
#Mapping(target="id", source="input.id"),
#Mapping(target="name", source="input.name")
})
EmployeeDTO inputToOutputDTO(Input entity);
#Mappings({
#Mapping(target="id", source="dto.id"),
#Mapping(target="name", source="dto.name")
})
Employee outputDTOtoInput(OutputDTO dto); }
But for your use case i think you will need to use Generic Type Converters. You will have to use java generics to define generic converters for each of the object type.One sample i found.
I have a DTO class with fields that either have javax or custom constraints put on them so everytime I hit this endpoint I am guaranteed to take in data that meets my requirements.
#PostMapping
public ResponseEntity<SomeResource> create(#Valid #RequestBody SomeDTO someDTO)
For reasons I do not want to go into, I am forced to validate this incoming data elsewhere (preferably in a separate service method) so I have tried doing:
#PostMapping
public ResponseEntity<SomeResource> create(#RequestBody SomeDTO someDTO) {
someService.validate(someDTO);
}
where the called method's signature is defined as
validate(#Valid SomeDTO someDTO)
Though I quickly figured out this does not actually do any other argument validation other than user input. With the Spring annotations not being particularly helpful, are there any other annotations out there that can validate an object passed in as a parameter to ensure the constraints are not violated?
I have JAX-RS API endpoints defined in a class. I have methods in the class such as
#GET
#Path("{param1}/{param2}/mypath")
#Consumes({ MediaType.APPLICATION_XML, MediaType.TEXT_XML,
MediaType.APPLICATION_JSON })
#Produces({ MediaType.APPLICATION_XML, MediaType.TEXT_XML,
MediaType.APPLICATION_JSON })
public Response getSomeResource(#PathParam("param1") MyClass1 myclass1,
#PathParam("param2") MyClass2 myclass2 )
{
//business logic goes here
}
Now as per the documentation at -- https://docs.oracle.com/cd/E19776-01/820-4867/6nga7f5n6/index.html , #QueryParam and #PathParam can only be used on the following Java types:
All primitive types except char
All wrapper classes of primitive types except Character
Have a constructor that accepts a single String argument
Any class with the static method named valueOf(String) that accepts
a single String argument
Any class with a constructor that takes a single String as a
parameter
List<T>, Set<T>, or SortedSet<T>, where T matches the already listed
criteria. Sometimes parameters may contain more than one value for
the same name. If this is the case, these types may be used to
obtain all values.
In the codebase, MyClass1 and MyClass2 don't follow any of the above yet everything works fine on PROD. But when I tried to test the same method with Jersey Test framework, jersey gives me the exception on startup :
org.glassfish.jersey.server.model.ModelValidationException: Validation of
the application resource model has failed during application initialization.
[[FATAL] No injection source found for a parameter of type public
javax.ws.rs.core.Response
On further digging I found that above conditions were required for my #PathParams/#QueryParams bindings for MyClass1 and MyClass2. I supplied a public constructor with a single String argument to MyClass1 and the problem disappeared partly. I tried the same with MyClass2 but the problem persisted. MyClass2 is a static inner class which has a parent class too. So here are my questions :
How is it working fine on PROD but complaining on JUnit test?
Are there any special considerations to be made for static inner classes to be used for binding #PathParams/#QueryParams? I gave a public constructor with single String arg to the static inner class but the problem still persisted while for the other class (MyClass1) it worked. Is there something which I am missing?
Thanks!
Suppose Animal is an abstract class in my project, and I have a REST resource (on a JAX-RS server, using Jackson for (de)serialization) for a PUT to manipulate animals that are stored in my database. They have concrete types, and the REST resource specifies the type in the path of the request:
#PUT
#Consumes(MediaType.APPLICATION_JSON)
#Path("/{entityType}/{id: \\d+}")
public <T extends Animal> void putAnimal(#PathParam("entityType") String entityType, #PathParam("id") String id, Animal input) throws IOException {
//...
}
I want to use entityType to pick the concrete class to deserialize with (Dog or Cat or whatever, for entityType being dog or cat or whatever). For reasons which are too complicated to explain here, I cannot put the type information in the JSON input itself.
So AIUI annotating Animal with a custom TypeIdResolver or something of the sort can't help me, because the type information won't be in the JSON itself (and that's all the info that the type resolver will get). I was planning to use a custom MessageBodyReader, but as far as I can tell, that doesn't get the other parameter values from the body passed in its readValue method, so I won't know what to deserialize into.
What am I missing? If this approach fails, how can I accomplish what I want without specifying animal-specific endpoints (which leads to lots of duplicate code as well as a loss of generality - right now I can add an subclass of Animal and this code will Just Work, which is very nice.)
The below quote from the JAX-RS specification (5.2.2 URIs and URI Templates) suggests that you should be able to inject a UriInfo instance into your custom MessageBodyReader, and use one of its methods to inspect the URL path of the request.
An instance of UriInfo can be injected into a class field or method parameter using the #Context an- notation. UriInfo provides both static and dynamic, per-request information, about the components of a request URI.
The example provided there shows a resource method receiving a UriInfo parameter, but normally it should be possible to inject an instance to a provider (MessageBodyReader) as well.
After obtaining the entityType path param through the UriInfo, your MessageBodyReader should be able to provide the corresponding sublclass of Animal.
Given what you are trying to do you are better off building an AnimalResource class which contains your basic methods and then building separate DogResource, CatResource and whatever other classes you need which extend AnimalResource. This will allow you to obtain the correct subclass of Animal and so deserialize the input JSON correctly.
Update
An example of how this might be achieved. Your base resource looks something like this:
public class AnimalResource<T extends Animal>
{
private final transient AnimalService<T> service;
public AnimalResource(final AnimalService<T> service)
{
this.service = service;
}
#Get
#Path("{id}")
#Produces(MediaType.APPLICATION_JSON)
public T getbyId(#PathParam("id") final String id)
{
return this.service.findById(id);
}
// Other CRUD methods go here
}
And then your individual animals, assuming that they all have the same setup, are simply:
#Path("/cats")
public class CatResource extends AnimalResource<Cat>
{
public CatResource(final CatService catService)
{
super(catService);
}
}
for a cat and
#Path("/dogs")
public class DogResource extends AnimalResource<Dog>
{
public DogResource(final DogService dogService)
{
super(dogService);
}
}
for a dog. They will inherit the standard CRUD methods from the parent, and any animal-specific methods can still go in the individual *Resource class.