2010-12-08 16 views
1

私のアプリケーション用のRESTful APIを開発中です。すべてのgetter(HTTP GETを使用する)は正常に動作します。私は働くために(POSTを使用する)保存メソッドを作ることができません。REST + Spring + POST with custom marshaller

私はテストにHTMLフォームとRESTClientを使用しています。

は、ここでこの方法は、ときに、クライアントポストConfigurationItemと呼ばれることが期待されている私のコントローラ

@Controller 
public class EntitiesController { 
@RequestMapping(value="/ci/save/", method = RequestMethod.POST) 
public ModelAndView saveConfigurationItem(@RequestBody ConfigurationItem body) { 
    System.out.println("saveConfigurationItem: body=" + body); 
    return createModelAndView("ci", Collections.emptyList()); 
} 
} 

です。 私はカスタムシリアル化形式を使用しています。 XMLやJSONではありません。 VCardまたはVCalendar形式です。私の最初のテストでは、以下のVCardを使用しました:

BEGIN:VCARD 
N:Pooh;Winnie 
FN:Winnie the Pooh 
TEL:tel:+441234567 
END:VCARD 

私はURL http://localhost:8080/core.solution-1.0/data/ci/save/に投稿しました。 は、ここで私が得る応答されています

415 
The server refused this request because the request entity is in a format not 
supported by the requested resource for the requested method() 

(*)ConfigurationItemは抽象クラスです。 CardEntryはそれを拡張します。私は両方を試みた。

メソッドパラメータをStringに変更しようとしました。この場合、メソッドは呼び出されますが、文字列は空です。 Webで見たような勧告の1つに従うと同じことが起こります。パラメータの型をMultiValueMapに変更し、単純なHTMLフォームからリクエストを送信しました。

marshal()がまったく呼び出されていないことがわかりました。

どういうところが間違っていますか?

これは私が持っているものです。 (私はここに関連するコードを置く。)

Spring構成

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" 
xmlns:context="http://www.springframework.org/schema/context" 
xmlns:oxm="http://www.springframework.org/schema/oxm" 
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd 
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd 
    http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm-3.0.xsd"> 

<import resource="classes/spring-config-prod.xml"/> 
<context:component-scan base-package="com.mycompany.solution.service" /> 


<bean class="org.springframework.web.servlet.view.BeanNameViewResolver" /> 

<bean id="ciCardView" class="com.mycompany.solution.service.VFormatView"> 
    <constructor-arg> 
    <bean class="com.mycompany.solution.service.VFormatMarshaller"> 
    <property name="packagesToScan" value="com.mycompany.solution.entity"/> 
    </bean> 
    </constructor-arg> 
</bean> 
</beans> 

マーシャラー

public class VFormatMarshaller implements Marshaller, Unmarshaller { 
@Override 
public void marshal(Object obj, Result result) 
    throws IOException/*, XmlMappingException*/ { 
    System.out.println("VFormatMarshaller.marshal(" + obj + ")"); 
    marshalStreamResult(obj, (StreamResult)result); 
} 

@Override 
public boolean supports(Class<?> paramClass) { 
    System.out.println("VFormatMarshaller.supports(" + paramClass + ")"); 
    boolean supports = new HashSet<String>(Arrays.asList(packagesToScan)).contains(paramClass.getPackage().getName()); 
    if (supports) { 
    return supports; 
    } 

    return Collection.class.isAssignableFrom(paramClass); 
} 

@Override 
public Object unmarshal(Source source) throws IOException/*, XmlMappingException*/ { 
    System.out.println("VFormatMarshaller.unmarshal(" + source + ")"); 
    return unmarshalStreamSource((StreamSource)source); 
} 
//// ............................. 
} 

ビュー(これが唯一のコンテンツタイプをオーバーライドするために書かれている)

public class VFormatView extends MarshallingView { 

public VFormatView() { 
    super(); 
    setContentType("application/vcard"); 
    System.out.println("VFormatView()"); 
} 

public VFormatView(Marshaller marshaller) { 
    super(marshaller); 
    setContentType("application/vcard"); 
    System.out.println("VFormatView(" + marshaller + ")"); 
} 
} 
+0

あなたがコントローラで入力したパラメータを使用すると、あなたがログに、例外を得るのですか? – codelark

答えて

2

@RequestBody/@ResponseBodyは、HttpMessageConverterの階層によってサポートされます。これは、ViewResolverとはまったく異なります。あなたに

あなたは(あなたがマーシャラー/アンマーシャラーの既存の実装に依存する必要がない場合やHttpMessageConverter独自に作成)適切なマーシャラー/アンマーシャラーとコンテンツタイプとMarshallingHttpMessageConverterを設定する必要がある場合、および構成されたインスタンスを供給AnnotationMethodHandlerAdapter

次のようにカスタムHttpMessageConveterを設定するには、少なくとも侵入方法はBeanPostProcessorを作成することです:

public class Configurer implements BeanPostProcessor { 
    public void postProcessAfterInitialization(String name, Object bean) { 
     if (bean instanceof AnnotationMethodHandlerAdapter) { 
      AnnotationMethodHandlerAdapter a = (AnnotationMethodHandlerAdapter) bean; 
      HttpMessageConverter[] convs = a.getMessageConverters(); 
      ... add new converter ... 
      a.setMessageConverters(convs); 
     } 
    } 
    ... 
} 
+0

ありがとう!参考のために良い設定例がありますか? – AlexR