0

Suppose I have a JAX-RS web service like this:

import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;

@Path("/somePath/{id}")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public class SomeObject {

    @PathParam("id")
    private String id;

    @GET
    @Path("/something")
    public String something() {

        DbObject dbObject = new DbObject(id);

        // return something

    }

    @POST
    @Path("/somethingElse")
    public void somethingElse(Arg1 arg1, Arg2 arg2) {

        DbObject dbObject  = new DbObject(id);

        // do something else with it

    }

    ...

}

The very first line in almost all my methods is creating my dbObject.

Is there a way to do that immediately after id is set?

Can I do that in the id setter? Will the setId method be called instead of populating the value of the id variable?

Or what other option do I have?

BCartolo
  • 720
  • 4
  • 21

1 Answers1

1

Quoting the @PathParam documentation:

The type of the annotated parameter, field or property must either:

  • Be PathSegment, the value will be the final segment of the matching part of the path. See UriInfo for a means of retrieving all request path segments.
  • Be List<javax.ws.rs.core.PathSegment>, the value will be a list of PathSegment corresponding to the path segment(s) that matched the named template parameter. See UriInfo for a means of retrieving all request path segments.
  • Be a primitive type.
  • 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.

If you meet one of the above criteria, you will be able to use:

@PathParam("id")
private DbObject dbObject;

Let's focus in the three last approaches. First, using a constructor with a single String argument:

public class DbObject {

    private String id;

    public DbObject(String id) {
        this.id = id;
    }

    ...
}

Alternatively you can use a valueOf(String) method:

public class DbObject {

    private String id;

    public DbObject(String id) {
        this.id = id;
    }

    public static DbObject valueOf(String id) {
        return new DbObject(id);
    }

    ...
}

Or define a ParamConverterProvider:

@Provider
public class DbObjectParamConverterProvider implements ParamConverterProvider {

    @Override
    public <T> ParamConverter<T> getConverter(Class<T> rawType, Type genericType, 
                                              Annotation[] annotations) {

        if (rawType.getName().equals(DbObject.class.getName())) {

            return new ParamConverter<T>() {

                @Override
                public T fromString(String value) {
                    return rawType.cast(new DbObject(value));
                }

                @Override
                public String toString(T value) {
                    return ((DbObject) value).getId();
                }
            };
        }

        return null;
    }
}
cassiomolin
  • 124,154
  • 35
  • 280
  • 359