Using #BeanParameter with Jersey - java

I am creating an restfull webservice using JAX-RS, I've started developing using Wildfly 8.2 and JEE7 and I was able to achieve this:
endpoint search method:
#GET
#Path("/consultar")
public Response consultar(
#QueryParam("offset") #DefaultValue(value = "0") Integer offSet,
#QueryParam("limit") #DefaultValue(value = "10") Integer limit,
#NotNull #BeanParam EmpresaDTO filtro) {
return super.consultar(offSet, limit, filtro);
}
endpoint abstraction search method:
#Override
public Response consultar(Integer offSet, Integer limit, #NotNull Object filtro) {
T filtroMaterializado = mapper.map(filtro, getClassType());
Example example = getExampleGenerator().generate(filtroMaterializado);
List<T> lista = getRepository().listar(offSet, limit, example);
return getOkResponse(lista);
}
Thats was working until I had the requisite of migrating to Tomcat, then I pick Jersey as my JAX-RS implementation. Now I get an big big error stacktrace, followerd by this warning at server startup:
WARNING: A HTTP GET method, public javax.ws.rs.core.Response br.com.logtec.delivery.resource.AbstractResource.consultar(java.lang.Integer,java.lang.Integer,java.lang.Object), should not consume any entity.
I've googled and I've found this: Using #Consume with GET request in Jersey Rest
But I rather stick with the javax api default annotation #BeanParam, furthermore theres no such annotation #InjectParam into jersey-container-servlet dependency.
So what I ask is, is there a way of using #BeanParam at #GET method? If not, how can I include #InjectParam without including the hole glassfish-embedded-web dependency?

Nevermind, I figured it out. The problem was that my Resource interface abstract methods were annotated by #GET, #POST... I ripped them out and it was solved. Thanks anyway

Related

Lazy loading object causing issue during serialization. Getting 500 internal server error

I have written API's which are resulting in 500 error when hit through postman or browser. However, when I debug and see server is not throwing any error and in fact returning a proper response. Other controller I have implemented in a similar way is returning expected result. below is my controller code. Has anyone faced similar situation. Kindly help.
#CrossOrigin
#GetMapping(value="/byPatientId/{patientId}", produces = "application/json")
public List<ContactInfo> getAllContacts(#PathVariable String patientId) {
logger.info("Received request for List of ContactInfo for patientId: "+patientId);
List<ContactInfo> list =
contactInfoService.getAllContacts(patientId);
return list;
}
#CrossOrigin
#GetMapping("/byContactId/{contactId}")
public ContactInfo getContactById(#PathVariable Integer contactId) {
logger.info("Received request for ContactInfo for contactId: "+contactId);
return contactInfoService.getContactById(contactId);
}
The problem was with one of the dependent object which was having oneToMany relationship with the return type object and it was set to Lazy loading and issue was during the serialization.
Either we can change it to Eager loading or ignore the dependent object by adding #JsonIgnore on dependent object.
I handled it by adding #JsonIgnore annotation on top of the dependent object as I don't need the dependent object in this particular usecase. Issue is solved now.
How is your Controller annotated? is it with #Controller or #Rest?
#RestController = #Controller + #ResponseBody(for serializing the response and pass it into the HttpResponse.
Add the #ResponseBody in your methods on the controller or change the #Controller tag into a #RestController(take into account that #RestController is available since 4.0 Spring version).
More info:https://www.baeldung.com/spring-controller-vs-restcontroller

Is Spring Boot WS SOAP endpoint able to works with reactive manner?

Let's say that my wsdl file says that this endpoint returns String but I want them to return Future or Mono.
When I just changed the returned type this is what I've got:
            <faultstring xml:lang="en">No adapter for endpoint [public reactor.core.publisher.Mono<java.lang.String> example.QuestionEndpoint.questionEndpoint(java.lang.String)]: Is your endpoint annotated with #Endpoint, or does it implement a supported interface like MessageHandler or PayloadEndpoint?</faultstring>
I've searched a lot of articles and forums and found only solutions for SOAP client.
#Endpoint
public class QuestionEndpoint {
#PayloadRoot(namespace = http://stack.org/, localPart = "Question")
#ResponsePayload
public String questionEndpoint(#RequestPayload String request) {
return facade.getQuestion(request)
.flatMap(result -> Mono.just(mapper.toDto(result)))
.block();;
}
}
In my code below endpoint I'm using Mono from 'reactor.core' and doing block() in endpoint just before return the result. Is it enough to work this endpoint in a reactive way?
If it's not enough, Is Spring Boot WS SOAP endpoint able to return some reactive type, even if my WSDL file require specific type?
In REST API it's kinda easy to implement it in a reactive way.

No cache header in Spring Boot response from RestController

I have a typical controller which returns JSON and I need to return no-cache header as a part of a response. Please note at this moment I have no spring security on classpath, however if there is need to make it to work out-of-the-box then I'm fine with this.
Currently I have implemented this in the following manner:
public static <T> ResponseEntity<T> createResponseSpringWay(final T body) {
org.springframework.http.CacheControl cacheControl = org.springframework.http.CacheControl.noCache();
return ResponseEntity.ok().cacheControl(cacheControl).body(body);
}
Is there any spring boot property that can make it automatically for me? I want to get rid of ResponseEntity at all methods.
I've tried the following configuration, but I believe it only applies to static resources, so it doesn't work:
spring.resources.cache.cachecontrol.no-store=true
spring.resources.cache.cachecontrol.must-revalidate=true
spring.resources.cache.cachecontrol.no-cache=true

Overriding RolesAllowedDynamicFeature in Jersey 2.5.1

Short and sweet:
I want to be able to filter incoming requests to authenticate the user then take the roles defined in my database and use them in the Jersey 2.5.1 Service classes.
e.g.
#RolesAllowed("Custom1", "Custom2")
#Post
.....
Currently I have the following, which seems to work with the basic #PermitAll and #DenyAll annotations, I am just not sure how to overload/what to overload to get some custom code working with Jersey 2.5.1. I've seen examples for Jersey1. Should I just create a request Filter and do it in there and set the securityContext? Any help would be appreciated.
public class TestApi extends ResourceConfig {
public TestApi() {
super(AuthenticateResource.class);
register(RolesAllowedDynamicFeature.class);
}
}
Figured out my problem. Injected Resource Info then pulled out the annotation. This works if it's not pre-matching
#Context
private ResourceInfo resourceInfo;
Annotation[] annotations = resourceInfo.getResourceMethod().getDeclaredAnnotations();
SecurityContext is either set by the underlying container or it's set manually in your application (usually in ContainerRequestFilter). If your container is sophisticated enough to set the correct security context for you (with correct principal) you can go this way. Otherwise create a custom ContainerRequestFilter similar to the one in Jersey example ContainerAuthFilter.

Null content-type when migrating from Jersey to RESTEasy.

So I wrote a sample REST resource that works like a charm in Jersey/Tomcat, but when I take it to RestEASY/Tomcat it blows. I mean really? what happened to working out of the box. Anyway a little frustrated. I get this error when trying to access the resource(http://localhost:7070/mg/mytest)
"content-type was null and expecting to extract a body"
7842 [http-7070-2] ERROR com.loyalty.mg.rest.exception.MGExceptionMapper - Error caught in the exception mapper -
org.jboss.resteasy.spi.BadRequestException: content-type was null and expecting to extract a body
at org.jboss.resteasy.core.MessageBodyParameterInjector.inject(MessageBodyParameterInjector.java:131)
at org.jboss.resteasy.core.MethodInjectorImpl.injectArguments(MethodInjectorImpl.java:98)
at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:121)
at org.jboss.resteasy.core.ResourceMethod.invokeOnTarget(ResourceMethod.java:247)
at org.jboss.resteasy.core.ResourceMethod.invoke(ResourceMethod.java:212)
at org.jboss.resteasy.core.ResourceMethod.invoke(ResourceMethod.java:202)
#Path("/mytest")
public class TestResource {
#GET
public Response getData()
I guess the question also is - is RestEASY any better than Jersey, this is just the start and I am getting errors. Should I just stick to Jersey?
Also already tried this as well :)
<context-param>
<param-name>resteasy.media.type.mappings</param-name>
<param-value>json : application/json, xml : application/xml</param-value>
</context-param>
The code that throws that exception looks like this:
final MediaType mediaType = request.getHttpHeaders().getMediaType();
if (mediaType == null) {
throw new BadRequestException(
"content-type was null and expecting to extract a body");
}
The problem seems to be that RestEASY cannot figure out a content type from the headers of the request that it received. This suggests that either that the content type in the request is bogus, or that there is a problem with the way that you have configured RestEASY.
I guess the question also is - is RestEASY any better than Jersey, this is just the start and I am getting errors. Should I just stick to Jersey?
I cannot answer that. However, I think you are being too quick to blame RestEASY for something that could be your code's fault.
A classic cause of this, is if you have code like this:
#GET
#Path("/foo/{bar}")
#Produces(MediaType.TEXT_HTML)
public Response foo(#PathParam("bar") String bar) {
...and you forget to annotate the bar argument with #PathParam. Then RestEasy thinks it should be reading bar from the body of the request, instead of from the URL path, and will chuck this exception.
That doesn't seem to be what's happening in your case, but I got the same exception, and this was the cause.
RestEASY vs Jersey is hard to say:
http://www.infoq.com/news/2008/10/jaxrs-comparison
Regarding your error, you can control the content type via annotations, what happens if you place #Produces annotation, for example:
#Produces("application/json")
#GET
public Response getData() {
...
}
Well I know this requested is dated, and so much on the internet old..in a year of two everything usually changes and works better. So RestEasy should not get a bad rap in comparison to other non-propertary RESTLET frameworks.
Actually I think JBoss RestEasy has the lightest footprint, it's not bloated with unnecessary *.jars, flexible, fully certified JAX-RS implementation, complete and its ease of use is beyond comparison.
Some eluded, that a GET request should not expect a Content_Type on the request, (And I agree), but with a every GET request one must indicate what you intend on sending back to the requestor? Right! (will it be JSON, XML, plain text, XML and a sheetsheet, multi-part, etc). Well RestEasy, JBoss's framework addresses this with annotation as shown below, and configurable per URL REST request. Therefore, therein is your answer
#GET
#Path("/echo/{message}")
#Produces("text/plain")
public String echo(#PathParam("message")String message){
return message;
}
#GET
#Path("/employees")
#Produces("application/xml")
#Stylesheet(type="text/css", href="${basepath}foo.xsl")
public List<Employee> listEmployees(){
return new ArrayList<Employee>(employees.values());
}
#GET
#Path("/employee/{employeeid}")
#Produces("application/xml")
public Employee getEmployee(#PathParam("employeeid")String employeeId){
return employees.get(employeeId);
}
#GET
#Path("/json/employees/")
**#Produces("application/json")**
public List<Employee> listEmployeesJSON(){
return new ArrayList<Employee>(employees.values());
}
a GET request must not have a body, and an application must not expet a Content-Type header.
If this is a bug of RestEASY, it makes one wonder how many people really are using the software.
EDIT
RFC2616 $4.3
A message-body MUST NOT be included in
a request if the specification of the
request method (section 5.1.1) does
not allow sending an entity-body in
requests.
A server SHOULD read and forward a
message-body on any request; if the
request method does not include
defined semantics for an entity-body,
then the message-body SHOULD be
ignored when handling the request.
The GET method does not "does not allow sending an entity-body in request" therefore a GET request COULD have a body. But GET "does not include defined semantics for an entity-body" therefore the body should be ignored anyway.
In any case, RestEASY should not have required the presence of Content-Type in a GET request.

Categories

Resources