<job/>
または<exception/>
常にステータスコードを返すサービスにRESTPOSTを作成する必要があります200
。(サードパーティ製品のラメ!)。
私は次のようなコードを持っています:
Job job = getRestTemplate().postForObject(url, postData, Job.class);
そして、私のapplicationContext.xmlは次のようになります。
<bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
<constructor-arg ref="httpClientFactory"/>
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter">
<property name="marshaller" ref="jaxbMarshaller"/>
<property name="unmarshaller" ref="jaxbMarshaller"/>
</bean>
<bean class="org.springframework.http.converter.FormHttpMessageConverter"/>
<bean class="org.springframework.http.converter.StringHttpMessageConverter"/>
</list>
</property>
</bean>
<bean id="jaxbMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="classesToBeBound">
<list>
<value>domain.fullspec.Job</value>
<value>domain.fullspec.Exception</value>
</list>
</property>
</bean>
この電話をかけようとしてサービスが失敗すると、次のようになります。
Failed to convert value of type 'domain.fullspec.Exception' to required type 'domain.fullspec.Job'
postForObject()呼び出しで、Job.classを要求していますが、取得していませんが、動揺しています。
私は次のようなことをする必要があると考えています。
Object o = getRestTemplate().postForObject(url, postData, Object.class);
if (o instanceof Job.class) {
...
else if (o instanceof Exception.class) {
}
しかし、これは機能しません。これは、JAXBがObject.classにマーシャリングする方法がわからないと文句を言うためです。当然のことながら。
MarshallingHttpMessageConverterのサブクラスを作成し、readFromSource()をオーバーライドしようとしました
保護されたオブジェクトreadFromSource(クラスクラズ、HttpHeadersヘッダー、ソースソース){
Object o = null;
try {
o = super.readFromSource(clazz, headers, source);
} catch (Exception e) {
try {
o = super.readFromSource(MyCustomException.class, headers, source);
} catch (IOException e1) {
log.info("Failed readFromSource "+e);
}
}
return o;
}
残念ながら、これは機能しません。これは、ソース内の基になる入力ストリームが、再試行するまでに閉じられているためです。
ありがたいことに受け取った提案、
トム
更新:inputStreamのコピーを取得することでこれを機能させることができます
protected Object readFromSource(Class<?> clazz, HttpHeaders headers, Source source) {
InputStream is = ((StreamSource) source).getInputStream();
// Take a copy of the input stream so we can use it for initial JAXB conversion
// and if that fails, we can try to convert to Exception
CopyInputStream copyInputStream = new CopyInputStream(is);
// input stream in source is empty now, so reset using copy
((StreamSource) source).setInputStream(copyInputStream.getCopy());
Object o = null;
try {
o = super.readFromSource(clazz, headers, source);
// we have failed to unmarshal to 'clazz' - assume it is <exception> and unmarshal to MyCustomException
} catch (Exception e) {
try {
// reset input stream using copy
((StreamSource) source).setInputStream(copyInputStream.getCopy());
o = super.readFromSource(MyCustomException.class, headers, source);
} catch (IOException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}
return o;
}
CopyInputStreamはhttp://www.velocityreviews.com/forums/t143479-how-to-make-a-copy-of-inputstream-object.htmlから取得されます。ここに貼り付けます。
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
public class CopyInputStream
{
private InputStream _is;
private ByteArrayOutputStream _copy = new ByteArrayOutputStream();
/**
*
*/
public CopyInputStream(InputStream is)
{
_is = is;
try
{
copy();
}
catch(IOException ex)
{
// do nothing
}
}
private int copy() throws IOException
{
int read = 0;
int chunk = 0;
byte[] data = new byte[256];
while(-1 != (chunk = _is.read(data)))
{
read += data.length;
_copy.write(data, 0, chunk);
}
return read;
}
public InputStream getCopy()
{
return (InputStream)new ByteArrayInputStream(_copy.toByteArray());
}
}