03. Param annotations, and param converters

This blog is based on Java Brains.

1. Resources class. PathParam and QueryParam


Let's make these changes

  • Insert {pParam} in the Path annotation of the class @Path("{pParam}/test")
  • Create 2 variables, the first annotated with javax.ws.rs.PathParam and the second one with javax.ws.rs.QueryParam.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package org.ximodante.jaxrs;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;


@Path("{pParam}/test02")
//@Singleton
public class MyResource02 {
 //private int count;
 @PathParam("pParam") private String pathParamExample;
 @QueryParam("qParam")   private String queryParamExample;
 
 @GET
 @Produces(MediaType.TEXT_PLAIN)
 public String testMethod() {
  //count=count +1;
  return "it works for me! \n" + 
    "pathParam=" + pathParamExample + "\n" + 
          "queryParam=" + queryParamExample ;
 }
}


Let's run and point to this URL:

http://localhost:8080/Jaxrs02/firstapi/myPParam/test02?qParam=myQParam

And the result is:


2. The @Singleton annotation problem

This annotation cannot be used in a Resource class that has params annotations as the resource is created once and the path variables cannot be reinitialized with the calls.


3. Param converters

Param converters should be used when the params types are not Strings, so a conversion is needed.
Let's create a class (that will have a converter).


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
package org.ximodante.jaxrs;

import lombok.Getter;
import lombok.Setter;

public class MyDate {
 @Getter @Setter
 private int date;
 @Getter @Setter
 private int month;
 @Getter @Setter
 private int year;
 
 @Override
 public String toString() {
  return "MyDate [date=" + date + ", month=" + month + ", year=" + year + "]" ;
 }
}

The resource class produces a compilation error until a converter is supplied. The error is in line 17 and reports:

The type 'org.ximodante.jaxrs.MyDate' is not valid for this parameter. See JAX-RS 2.0 Specification  (section 3.2) for more information.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
package org.ximodante.jaxrs;


import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;


@Path("test03/{dateString}")
//@Singleton
public class MyResource03 {
  
 @GET
 @Produces(MediaType.TEXT_PLAIN)
 public String testMethod(@PathParam("dateString") MyDate myDate) {
  //count=count +1;
  return "Date got: " + myDate.toString() ;
 }
}

Let's create the converter and the compilation error disappears:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package org.ximodante.jaxrs;

import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.Calendar;

import javax.ws.rs.ext.ParamConverter;
import javax.ws.rs.ext.ParamConverterProvider;
import javax.ws.rs.ext.Provider;

@Provider
public class MyDateConverterProvider implements ParamConverterProvider {

 @Override
 public <T> ParamConverter<T> getConverter(Class<T> rawType, Type genericType, Annotation[] annotations) {
  if (rawType.getName().equals(MyDate.class.getName())) {
   return new ParamConverter<T>() {

    @Override
    public T fromString(String value) {
     Calendar requestedDate = Calendar.getInstance();
     if ("tomorrow".equalsIgnoreCase(value)) {
      requestedDate.add(Calendar.DATE, 1);
     } else if ("yesterday".equalsIgnoreCase(value)) {
      requestedDate.add(Calendar.DATE, -1);
     }
     MyDate myDate= new MyDate();
     myDate.setDate(requestedDate.get(Calendar.DAY_OF_MONTH));
     myDate.setMonth(requestedDate.get(Calendar.MONTH));
     myDate.setYear(requestedDate.get(Calendar.YEAR));
     return rawType.cast(myDate);
    }

    @Override
    public String toString(T myBean) {
     if (myBean == null) {
      return null;
     } 
     return myBean.toString();
    }
    
   };
  }
  return null;
 }

}


The converter must implement an interface called ParamConverterProvider. This interface has a method that returns a ParamConverter implementation.

The ParamConverter interface has 2 methods that should be implemented:

  • T fromString(String value) That convert from string to our class (MyDate)
  • String toString(T myBean) Similar to "toString" method for converting a class to a string.
The idea is to pass the word "yesterday" or "tomorrow" to the URL call and transform to a bean of type MyDate.

The URL is:

http://localhost:8080/Jaxrs02/firstapi/test03/tomorrow

And the result is










Comentarios

Entradas populares de este blog

04. MessageBodyReaders and MessageBodyWriters. Custom Media Types

01. Let's go! Creating a Java Project