ラベル RESTEasy の投稿を表示しています。 すべての投稿を表示
ラベル RESTEasy の投稿を表示しています。 すべての投稿を表示

2013年11月13日水曜日

RESTEasy の Bean Validation

そんなの API で受けてから手動でやりなさいよ!と言われるかもしれないけどできることなら冗長なコードは排除したい。

そんなあなたに ExceptionMapper を使う方法を。

使い方が変わったようなので新旧書いときます。(大体同じようなことはしてますが全く同じではないので注意)

※RESTEasy 2.3 の方は EJB との組み合わせに問題がある・・・・ので、できれば RESTEasy 3 の方がおすすめです。

□WildFly 8.0.0.Beta1 & RESTEasy 3.0.4.Final
@Provider
public class ValidationExceptionHandler implements
        ExceptionMapper<ResteasyViolationException> {

    @Override
    @Produces(MediaType.APPLICATION_JSON)
    public Response toResponse(ResteasyViolationException exception) {

        ValidateMessage errors = new ValidateMessage();

        for (ResteasyConstraintViolation violation : exception.getViolations()) {
            errors.getMessages().add(
                    new Message(String.format("%s:%s:%s:%s", violation
                            .getPath(), violation.getConstraintType().name(),
                            violation.getValue(), violation.getMessage())));
        }

        return Response.status(Status.BAD_REQUEST).entity(errors).build();
    }
}
□JBoss AS 7.1.x & RESTEasy 2.3.x
@Provider
public class ValidationExceptionHandler implements
        ExceptionMapper<MethodConstraintViolationException> {

    @Override
    @Produces({ MediaType.APPLICATION_JSON })
    public Response toResponse(MethodConstraintViolationException ex) {
        ValidateMessage errors = new ValidateMessage();

        for (MethodConstraintViolation<?> violation : ex
                .getConstraintViolations()) {
            errors.getMessages().add(
                    new Message(String.format("%s:%s:%s:%s", violation
                            .getMethod().getName(), violation
                            .getParameterName(), violation.getInvalidValue(),
                            violation.getMessage())));
        }

        return Response.status(Status.BAD_REQUEST).entity(errors).build();
    }
}

□JSON 出力のためのドメインクラス
@XmlRootElement(name = "validate_message")
public class ValidateMessage implements Serializable {
    private static final long serialVersionUID = 1L;

    private List<Message> messages = new ArrayList<Message>();

    public static class Message {

        private String message;

        public Message() {
        }

        public Message(String message) {
            this.message = message;
        }

        public String getMessage() {
            return message;
        }

        public void setMessage(String message) {
            this.message = message;
        }

    }

    @XmlElementWrapper(name = "messages")
    @XmlElement(name = "message")
    public List<Message> getMessages() {
        return messages;
    }

    public void setMessages(List<Message> messages) {
        this.messages = messages;
    }
}

□pom.xml(RESTEasy 3.0.4.Final)
        <dependency>
            <groupId>org.jboss.resteasy</groupId>
            <artifactId>resteasy-validator-provider-11</artifactId>
            <version>3.0.4.Final</version>
            <scope>provided</scope>
        </dependency>
 □pom.xml(RESTEasy 2.3.x)
        <dependency>
            <groupId>org.jboss.resteasy</groupId>
            <artifactId>resteasy-hibernatevalidator-provider</artifactId>
            <version>2.3.7.Final</version>
        </dependency>

2013年1月8日火曜日

Servlet3 で、SetCharacterEncodingFilter

あけおめことよろ。

ってことで、Servlet3 で、フォーム文字化け回避ってどうするの?
って思ったらすぐ見つかった。

SetCharacterEncodingFilter 使って tomcat の例の文字化けを回避したい
http://d.hatena.ne.jp/Yoshiori/20111102/1320242301

web.xml への設定は不要。

JBoss 7.1 & RESTEasy に適用したけど大丈夫でしたよ。当たり前か。

2012年12月19日水曜日

RESTEasy を使ったバリデーション(続編)

この前ご紹介した、RESTEasy の Bean Validator を使ってみようと思ったら、こんなエラーが。orz


22:36:21,356 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/rest].[jp.vyw.rest.sample.SampleApplication]] (http--127.0.0.1-8080-1) サーブレット jp.vyw.rest.sample.SampleApplication のServlet.service()が例外を投げました: org.jboss.resteasy.spi.UnhandledException: javax.validation.ConstraintDeclarationException: Only the root method of an overridden method in an inheritance hierarchy may be annotated with parameter constraints, but there are parameter constraints defined at all of the following overridden methods: [MethodMetaData [method=public abstract void jp.vyw.rest.sample.api.ISample.insert(java.lang.String,java.lang.String), parameterMetaData=[ParameterMetaData [type=class java.lang.String], [index=0], name=arg0], constraints=[NotNull, Size], isCascading=false], ParameterMetaData [type=class java.lang.String], [index=1], name=arg1], constraints=[], isCascading=false]], constraints=[], isCascading=false, hasParameterConstraints=true], MethodMetaData [method=public void jp.vyw.rest.sample.api.ISample$$$view33.insert(java.lang.String,java.lang.String), parameterMetaData=[ParameterMetaData [type=class java.lang.String], [index=0], name=arg0], constraints=[NotNull, Size], isCascading=false], ParameterMetaData [type=class java.lang.String], [index=1], name=arg1], constraints=[], isCascading=false]], constraints=[], isCascading=false, hasParameterConstraints=true]]
        at org.jboss.resteasy.core.SynchronousDispatcher.handleException(SynchronousDispatcher.java:245) [resteasy-jaxrs-2.3.2.Final.jar:]
        at org.jboss.resteasy.core.SynchronousDispatcher.handleInvokerException(SynchronousDispatcher.java:190) [resteasy-jaxrs-2.3.2.Final.jar:]
        at org.jboss.resteasy.core.SynchronousDispatcher.getResponse(SynchronousDispatcher.java:540) [resteasy-jaxrs-2.3.2.Final.jar:]
        at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:502) [resteasy-jaxrs-2.3.2.Final.jar:]
        at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:119) [resteasy-jaxrs-2.3.2.Final.jar:]
        at org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:208) [resteasy-jaxrs-2.3.2.Final.jar:]
        at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:55) [resteasy-jaxrs-2.3.2.Final.jar:]
        at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:50) [resteasy-jaxrs-2.3.2.Final.jar:]
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:847) [jboss-servlet-api_3.0_spec-1.0.0.Final.jar:1.0.0.Final]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:329) [jbossweb-7.0.13.Final.jar:]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248) [jbossweb-7.0.13.Final.jar:]
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:275) [jbossweb-7.0.13.Final.jar:]
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161) [jbossweb-7.0.13.Final.jar:]
        at org.jboss.as.jpa.interceptor.WebNonTxEmCloserValve.invoke(WebNonTxEmCloserValve.java:50) [jboss-as-jpa-7.1.1.Final.jar:7.1.1.Final]
        at org.jboss.as.web.security.SecurityContextAssociationValve.invoke(SecurityContextAssociationValve.java:153) [jboss-as-web-7.1.1.Final.jar:7.1.1.Final]
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:155) [jbossweb-7.0.13.Final.jar:]
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) [jbossweb-7.0.13.Final.jar:]
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) [jbossweb-7.0.13.Final.jar:]
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:368) [jbossweb-7.0.13.Final.jar:]
        at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:877) [jbossweb-7.0.13.Final.jar:]
        at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:671) [jbossweb-7.0.13.Final.jar:]
        at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:930) [jbossweb-7.0.13.Final.jar:]
        at java.lang.Thread.run(Thread.java:679) [rt.jar:1.6.0_24]
Caused by: javax.validation.ConstraintDeclarationException: Only the root method of an overridden method in an inheritance hierarchy may be annotated with parameter constraints, but there are parameter constraints defined at all of the following overridden methods: [MethodMetaData [method=public abstract void jp.vyw.rest.sample.api.ISample.insert(java.lang.String,java.lang.String), parameterMetaData=[ParameterMetaData [type=class java.lang.String], [index=0], name=arg0], constraints=[NotNull, Size], isCascading=false], ParameterMetaData [type=class java.lang.String], [index=1], name=arg1], constraints=[], isCascading=false]], constraints=[], isCascading=false, hasParameterConstraints=true], MethodMetaData [method=public void jp.vyw.rest.sample.api.ISample$$$view33.insert(java.lang.String,java.lang.String), parameterMetaData=[ParameterMetaData [type=class java.lang.String], [index=0], name=arg0], constraints=[NotNull, Size], isCascading=false], ParameterMetaData [type=class java.lang.String], [index=1], name=arg1], constraints=[], isCascading=false]], constraints=[], isCascading=false, hasParameterConstraints=true]]
        at org.hibernate.validator.metadata.AggregatedMethodMetaData$Builder.checkParameterConstraints(AggregatedMethodMetaData.java:222) [hibernate-validator-4.2.0.Final.jar:4.2.0.Final]
        at org.hibernate.validator.metadata.AggregatedMethodMetaData$Builder.build(AggregatedMethodMetaData.java:161) [hibernate-validator-4.2.0.Final.jar:4.2.0.Final]
        at org.hibernate.validator.metadata.BeanMetaDataImpl.buildMethodMetaData(BeanMetaDataImpl.java:391) [hibernate-validator-4.2.0.Final.jar:4.2.0.Final]
        at org.hibernate.validator.metadata.BeanMetaDataImpl.<init>(BeanMetaDataImpl.java:286) [hibernate-validator-4.2.0.Final.jar:4.2.0.Final]
        at org.hibernate.validator.metadata.BeanMetaDataImpl.<init>(BeanMetaDataImpl.java:163) [hibernate-validator-4.2.0.Final.jar:4.2.0.Final]
        at org.hibernate.validator.engine.ValidatorImpl.getBeanMetaData(ValidatorImpl.java:1211) [hibernate-validator-4.2.0.Final.jar:4.2.0.Final]
        at org.hibernate.validator.engine.ValidatorImpl.validateInContext(ValidatorImpl.java:302) [hibernate-validator-4.2.0.Final.jar:4.2.0.Final]
        at org.hibernate.validator.engine.ValidatorImpl.validate(ValidatorImpl.java:139) [hibernate-validator-4.2.0.Final.jar:4.2.0.Final]
        at org.jboss.resteasy.plugins.validation.hibernate.HibernateValidatorAdapter.applyValidation(HibernateValidatorAdapter.java:39) [resteasy-hibernatevalidator-provider-2.3.2.Final.jar:]
        at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:150) [resteasy-jaxrs-2.3.2.Final.jar:]
        at org.jboss.resteasy.core.ResourceMethod.invokeOnTarget(ResourceMethod.java:257) [resteasy-jaxrs-2.3.2.Final.jar:]
        at org.jboss.resteasy.core.ResourceMethod.invoke(ResourceMethod.java:222) [resteasy-jaxrs-2.3.2.Final.jar:]
        at org.jboss.resteasy.core.ResourceMethod.invoke(ResourceMethod.java:211) [resteasy-jaxrs-2.3.2.Final.jar:]
        at org.jboss.resteasy.core.SynchronousDispatcher.getResponse(SynchronousDispatcher.java:525) [resteasy-jaxrs-2.3.2.Final.jar:]
        ... 20 more
いやーん・・・・・。

詳しくまとまってるサイトを見つけたですが、関連は不明だけど、こんなことが書いてある。
To provide translations to other languages, one must create a new ValidationMessages_XX.properties file with the translated messages, where XX is the code of the language being provided.

Unfortunately Hibernate Validator provider doesn’t supports I18N based on a specific HTTP request. It does not take Accept-Language HTTP header into account and always uses the default Locale as provided by Locale.getDefault(). To be able to change the Locale using the Accept-Language HTTP header, a custom implementation must be provided.

んー、もうちょっと頑張ってみる。

2012年11月1日木曜日

RESTEasy を使ったバリデーション

久々の更新です。
少し落ち着いてきたので、コンスタントに更新するようにしたいと思います。

さて、RESTEasy ってバリデーション使えなくて不便なんだよねー。いつか実装されるのかなぁ?と思っていたら、2.3 から Bean Validator が使えるようになってました☆
 http://docs.jboss.org/resteasy/docs/2.3.5.Final/userguide/html/Validation.html

API だって当然バリデーションは必要ですよね。この機能が後回しにされた理由が不明ですが、実装されて良かった良かった。