13.10. Annotations basées chaîne

13.10.1. Conversion des annotations basées @*Param en objects

Les annotations @*Param JAX-RS,@PathParam et @FormParam incluses, sont représentées par des chaînes dans une requête HTTP brut. Ces types de paramètres injectés peuvent être convertis en objets si ces objets ont une méthode valueOf(String) statique ou un constructeur qui prend un paramètre String.
RESTEasy fournit deux interfaces @Provider commerciales pour effectuer cette conversion pour les classes qui n'ont ni de méthode valueOf(String) statique, ni de constructeur de string.

Exemple 13.11. StringConverter

L'interface StringConverter est mise en place afin de fournir un marshalling de chaîne personnalisée. Elle est inscrite dans resteasy.providers context-param du fichier web.xml. Elle peut également être enregistrée manuellement en appelant la méthode ResteasyProviderFactory.addStringConverter().
L'exemple suivant est un simple exemple de StringConverter.
import org.jboss.resteasy.client.ProxyFactory;
import org.jboss.resteasy.spi.StringConverter;
import org.jboss.resteasy.test.BaseResourceTest;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import javax.ws.rs.HeaderParam;
import javax.ws.rs.MatrixParam;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.QueryParam;
import javax.ws.rs.ext.Provider;

public class StringConverterTest extends BaseResourceTest
{
  public static class POJO
  {
     private String name;

     public String getName()
     {
	return name;
     }

     public void setName(String name)
     {
	this.name = name;
     }
  }

  @Provider
  public static class POJOConverter implements StringConverter<POJO>
  {
     public POJO fromString(String str)
     {
	System.out.println("FROM STRNG: " + str);
	POJO pojo = new POJO();
	pojo.setName(str);
	return pojo;
     }

     public String toString(POJO value)
     {
	return value.getName();
     }
  }

  @Path("/")
  public static class MyResource
  {
     @Path("{pojo}")
     @PUT
     public void put(@QueryParam("pojo")POJO q, @PathParam("pojo")POJO pp,
		     @MatrixParam("pojo")POJO mp, @HeaderParam("pojo")POJO hp)
     {
	Assert.assertEquals(q.getName(), "pojo");
	Assert.assertEquals(pp.getName(), "pojo");
	Assert.assertEquals(mp.getName(), "pojo");
	Assert.assertEquals(hp.getName(), "pojo");
     }
  }

  @Before
  public void setUp() throws Exception
  {
     dispatcher.getProviderFactory().addStringConverter(POJOConverter.class);
     dispatcher.getRegistry().addPerRequestResource(MyResource.class);
  }

  @Path("/")
  public static interface MyClient
  {
     @Path("{pojo}")
     @PUT
     void put(@QueryParam("pojo")POJO q, @PathParam("pojo")POJO pp,
	      @MatrixParam("pojo")POJO mp, @HeaderParam("pojo")POJO hp);
  }

  @Test
  public void testIt() throws Exception
  {
     MyClient client = ProxyFactory.create(MyClient.class, "http://localhost:8081");
     POJO pojo = new POJO();
     pojo.setName("pojo");
     client.put(pojo, pojo, pojo, pojo);
  }
}

Exemple 13.12. StringParameterUnmarshaller

L'interface StringParameterUnmarshaller est sensible aux annotations placées sur le paramètre ou le champ sur lesquels vous injectez. Il est créé par injecteur. La méthode setAnnotations() est appelée par resteasy pour initialiser l'unmarshaller.
Cette interface peut être ajoutée en créant et en enregistrant un fournisseur qui implémente l'interface. Il peut être également lié à une meta-annotations appelée org.jboss.resteasy.annotations.StringsParameterUnmarshallerBinder.
L'exemple ci-dessous formate un java.util.Date basé @PathParam.
public class StringParamUnmarshallerTest extends BaseResourceTest
{
   @Retention(RetentionPolicy.RUNTIME)
   @StringParameterUnmarshallerBinder(DateFormatter.class)
   public @interface DateFormat
   {
      String value();
   }

   public static class DateFormatter implements StringParameterUnmarshaller<Date>
   {
      private SimpleDateFormat formatter;

      public void setAnnotations(Annotation[] annotations)
      {
         DateFormat format = FindAnnotation.findAnnotation(annotations, DateFormat.class);
         formatter = new SimpleDateFormat(format.value());
      }

      public Date fromString(String str)
      {
         try
         {
            return formatter.parse(str);
         }
         catch (ParseException e)
         {
            throw new RuntimeException(e);
         }
      }
   }

   @Path("/datetest")
   public static class Service
   {
      @GET
      @Produces("text/plain")
      @Path("/{date}")
      public String get(@PathParam("date") @DateFormat("MM-dd-yyyy") Date date)
      {
         System.out.println(date);
         Calendar c = Calendar.getInstance();
         c.setTime(date);
         Assert.assertEquals(3, c.get(Calendar.MONTH));
         Assert.assertEquals(23, c.get(Calendar.DAY_OF_MONTH));
         Assert.assertEquals(1977, c.get(Calendar.YEAR));
         return date.toString();
      }
   }

   @BeforeClass
   public static void setup() throws Exception
   {
      addPerRequestResource(Service.class);
   }

   @Test
   public void testMe() throws Exception
   {
      ClientRequest request = new ClientRequest(generateURL("/datetest/04-23-1977"));
      System.out.println(request.getTarget(String.class));
   }
}
Définit une nouvelle annotation appelée @DateFormat. L'annotation est annotée avec la meta-annotation StringParameterUnmarshallerBinder avec une référence aux classes DateFormater.
La méthode Service.get() possède un paramètre @PathParam qui est aussi annoté avec @DateFormat. L'application @DateFormat déclenche la liaison du DateFormatter. Le DateFormatter sera désormais exécuté pour supprimer le marshalling du paramètre de chemin d'accès dans le paramètre date de la méthode get().