14

I got a weird problem, that I absolutely doesn't understand, with Jersey 2.6.

I can't explain why, but one of the query parameter make jersey throw a ModelValidationException

    @ApiOperation("Save")
    @PUT
    public Response save(
            @HeaderParam("token") final String token,
            @QueryParam("someValue") final SomeValueDTO someValue,
            @QueryParam("anotherParam") final int anotherParam) throws TechnicalException {

        return Response.ok().build();
    }

the queryParam 'someValue' make jersey throw:

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 ch.rodano.studies.api.resources.PagesResource.save(java.lang.String,ch.rodano.studies.api.dto.JSONValueDTO,int) throws ch.rodano.studies.exceptions.RightException,ch.rodano.studies.configuration.exceptions.NoNodeException at index 1.; source='ResourceMethod{httpMethod=PUT, consumedTypes=[], producedTypes=[application/json], suspended=false, suspendTimeout=0, suspendTimeoutUnit=MILLISECONDS, invocable=Invocable{handler=ClassBasedMethodHandler{handlerClass=class ch.rodano.studies.api.resources.PagesResource, handlerConstructors=[org.glassfish.jersey.server.model.HandlerConstructor@41ed3918]}, definitionMethod=public javax.ws.rs.core.Response ch.rodano.studies.api.resources.PagesResource.save(java.lang.String,ch.rodano.studies.api.dto.JSONValueDTO,int) throws ch.rodano.studies.exceptions.RightException,ch.rodano.studies.configuration.exceptions.NoNodeException, parameters=[Parameter [type=class java.lang.String, source=token, defaultValue=null], Parameter [type=class ch.rodano.studies.api.dto.JSONValueDTO, source=valuesASD, defaultValue=null], Parameter [type=int, source=visitPk, defaultValue=null]], responseType=class javax.ws.rs.core.Response}, nameBindings=[]}']

If I use String instead of SomeValueDTO everything's okay. SomeValueDTO is a quite classic POJO with an empty constructor and getters/setters.

If someone has an idiea !!

tanou
  • 1,083
  • 2
  • 13
  • 33

3 Answers3

19

SomeValueDTO needs to be convertible. Options to accomplish this:

  1. A public static SomeValueDTO valueOf(String param) that returns the type (SomeValueDTO)
  2. A public static SomeValueDTO fromString(String param) that returns the type (SomeValueDTO)
  3. Or a public constructor that accepts a String
  4. Implement a ParamConverter. You can see an example here

In either of the first three cases, you'll want to construct the instance accordingly by parsing the String either in the constructor or in one of the above-mentioned methods.

Generally, you'll only want to use the ParamConverter for third-party classes that you cannot edit. Otherwise use the other three options for your own classes.

Deepak Patankar
  • 3,076
  • 3
  • 16
  • 35
Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720
  • Thanks the quick answer ! So if I understand, I have to parse myself the jsonString into the object ? SomeValueDTO only contains simple type like String or int, there is no way to make jersey parse it automatically ? – tanou Apr 16 '15 at 13:50
  • It doesn't matter. How do you expect Jersey to know how to convert a String to a random object? It doesn't know it is JSON coming in. Personally, I would never send JSON in a query string. That's just me. Those four things I mentioned are part of the specification on how to inject objects for `@XxxParam`s. All the params values come in as Strings. So we need to tell Jersey how to convert it – Paul Samsotha Apr 16 '15 at 13:51
  • okay, I guess I was expecting too much from it. Kinda regret Spring ;) thanks again! – tanou Apr 16 '15 at 13:54
  • this is a good answer, you covered all the options available. I have upvoted to cancel out the down vote. Not sure why someone would downvote. – David Roussel Jun 17 '16 at 15:10
3

From Jersey 2.0, you can use @BeanParam as input but you must set all @QueryParam in the DTO variables:

@ApiOperation("Save")
@PUT
public Response save(@BeanParam SomeValueDTO inputValue) 
{
   String prop1 = inputValue.prop1;
   String prop2 = inputValue.prop2;
   String prop3 = inputValue.prop3;
}

SomeValueDTO.java will be:

public class SomeValueDTO{
 @QueryParam("prop1") 
 public String prop1;

 @QueryParam("prop2") 
 public String prop2;

 @QueryParam("prop3") 
 public String prop3;
}

The http call can be:

$http.get('insert-path', {
    params: {
         prop1: "prop1value",
         prop2: "prop2value",
         prop3: "prop3value"
 }});

Source answer: https://stackoverflow.com/a/17309823/3410465

Diego87
  • 1,617
  • 3
  • 17
  • 20
  • Because i fixed the same problem in this way, so if you want to send a POJO that is what he wanted to do, you can use this way too without get exception. – Diego87 Mar 28 '19 at 17:57
0

I had the same problem. Just put next in your web.xml

<servlet>
<servlet-name>jersey</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>
org.glassfish.jersey.media.multipart.MultiPartFeature;
org.glassfish.jersey.filter.LoggingFilter
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
  • Not every ModelValidationException is the same. Please read the question (and not just the title) before answering. Your solution is for getting the error when using Multipart, which is not the same as this case. -1. – Paul Samsotha Mar 11 '19 at 11:22