12.10. 文字列ベースのアノテーション

12.10.1. 文字列ベースの @*Param Annotations をオブジェクトに変換

@PathParam や @FormParamJAX-RS などの @*Param アノテーションは、Raw HTTP リクエストの文字列として表現されます。これらのオブジェクトにvalueOf(String) の静的メソッドあるいは String パラメーターを取るコンストラクターが含まれている場合、注入されたパラメーターの型をオブジェクトに変換することが可能です。
RESTEasy は専用の @Provider インターフェースを2つ提供し、valueOf(String) の静的メソッドあるいは文字列コンストラクターのいずれも持たないクラスに対して、この変換処理を行います。

例12.11 StringConverter

StringConverter インターフェースは、カスタム文字列のマーシャリングが行えるよう実装されています。このインターフェースは web.xml ファイルの resteasy.providers context-param 下で登録されています。また、ResteasyProviderFactory.addStringConverter() メソッドを呼び出すことにより手動で登録することもできます。
以下の例は、簡単な 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);
  }
}

例12.12 StringParameterUnmarshaller

StringParameterUnmarshaller インターフェースは、パラメーターに付けられたアノテーションや、注入先のフィールドからの影響を受けます。これは、インジェクターごとに作成されます。setAnnotations() メソッドは、resteasy に呼び出されアンマーシャラーを初期化します。
インターフェースを実装するプロバイダーを作成、登録することで、このインターフェースを追加できます。また、 org.jboss.resteasy.annotations.StringsParameterUnmarshallerBinder と呼ばれる meta-annotation を使いバインドすることもできます。
以下の例では、java.util.Date ベースの @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));
   }
}
@DateFormat と呼ばれる新しいアノテーションを定義します。このアノテーションは、DateFormater クラスへの参照を持つ meta-annotation StringParameterUnmarshallerBinder で注釈されます。
Service.get() メソッドには@DateFormat のアノテーションもついた @PathParam パラメーターがあります。@DateFormat を適用すると、DateFormatter のバインディングがトリガーされます。すると、DateFormatter が実行され、get() メソッドの date パラメーターへ path パラメーターをアンマーシャリングします。

このページには機械翻訳が使用されている場合があります (詳細はこちら)。