#java #spring #cxf #cxfrs #cxf-client
#java #весна #cxf #cxfrs #cxf-client
Вопрос:
У меня есть полностью функциональная настройка JAXRS REST API с использованием CXF и Spring. Однако, похоже, я не могу поручить своим прокси-сервисам использовать настройку use my JAXB для де-сериализации моих временных параметров JODA.
Я получаю сообщение об исключении: Parameter Class org.joda.time.DateTime has no constructor with single String parameter, static valueOf(String) or fromString(String) methods
Я настроил a ParamConverterProvider
для обработки преобразования, но, похоже, это не улавливается (при отладке он не вызывает my ParamConverterProviderImpl
). Как я могу сказать cxf использовать его и для моих прокси.
Я использую CXF 3.0.0, и моя настройка выглядит следующим образом:
У меня есть служба JAXRS
@Path("/entries")
@Produces({"application/json", "application/xml"})
@Consumes({"application/json", "application/xml", "text/xml"})
public interface RSEntryService {
@GET
@Path("/summed")
public ApiEntries getSummedEntries(@QueryParam("") ApiDateRangeFilter filter) throws Exception;
}
С реализацией
public class RSEntryServiceImpl implements RSEntryService {
@Override
public ApiEntries getSummedEntries(ApiDateRangeFilter filter) throws Exception {
... do stuff ...
}
Где ApiDateRangeFilter выглядит следующим образом
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "daterangefilter")
public class ApiDateRangeFilter {
@XmlJavaTypeAdapter(value=DateAdapter.class)
private DateTime start;
@XmlJavaTypeAdapter(value=DateAdapter.class)
private DateTime end;
... getters and setters ...
}
сервисы подключены следующим образом:
<jaxrs:server id="rsAPIServices"
address="${joostschouten.businessadmin.api.rs.server.address}">
<jaxrs:serviceBeans>
<ref bean="com.joostschouten.businessadmin.api.rs.RSEntryService" />
<!-- Swagger API Listing resource -->
<ref bean="swaggerResourceJSON" />
</jaxrs:serviceBeans>
<jaxrs:extensionMappings>
<entry key="xml" value="application/xml" />
<entry key="json" value="application/json" />
</jaxrs:extensionMappings>
<jaxrs:providers>
<bean class="com.joostschouten.businessadmin.api.rs.parameterhandlers.ParamConverterProviderImpl" />
<ref bean="jaxrsJsonProvider"/>
<!-- <ref bean="jaxrsJsonProvider"/> -->
<bean class="com.joostschouten.businessadmin.api.rs.exception.RSExceptionMapper" />
<!-- required for writing swagger classes -->
<ref bean="resourceWriter" />
<ref bean="apiWriter" />
</jaxrs:providers>
<jaxrs:inInterceptors>
<bean class="org.apache.cxf.jaxrs.provider.jsonp.JsonpInInterceptor" />
<ref bean="depthInterceptor" />
</jaxrs:inInterceptors>
<jaxrs:outInterceptors>
<bean class="org.apache.cxf.jaxrs.provider.jsonp.JsonpPreStreamInterceptor" />
<bean class="org.apache.cxf.jaxrs.provider.jsonp.JsonpPostStreamInterceptor" />
</jaxrs:outInterceptors>
</jaxrs:server>
<bean id="jaxrsJsonProvider" class="org.apache.cxf.jaxrs.provider.json.JSONProvider">
<property name="dropRootElement" value="${joostschouten.businessadmin.api.rs.dropJsonRootElement}" />
<property name="supportUnwrapped" value="${joostschouten.businessadmin.api.rs.supportUnwrappedJson}" />
</bean>
И я настроил прокси для использования в своих тестах, который настроен
<jaxrs-client:client address="${joostschouten.businessadmin.api.rs.server.address}"
id="com.joostschouten.businessadmin.api.rs.RSEntryService.proxy"
serviceClass="com.joostschouten.businessadmin.api.rs.RSEntryService">
<jaxrs-client:providers>
<bean class="com.joostschouten.businessadmin.api.rs.parameterhandlers.ParamConverterProviderImpl" />
</jaxrs-client:providers>
</jaxrs-client:client>
ParamConverterProvider
@Provider
public class ParamConverterProviderImpl implements ParamConverterProvider {
@Override
public <T> ParamConverter<T> getConverter(Class<T> rawType, Type genericType, Annotation[] annotations) {
if(rawType.equals(LocalDate.class)) {
return (ParamConverter<T>) new LocalDateHandler();
}
else if (rawType.equals(Date.class)) {
return (ParamConverter<T>) new DateHandler();
}
return null;
}
}
В моем тесте, где я использую прокси, у меня есть:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath*:/spring/test-joostschouten-businessadmin-beans.xml"})
public class RSEntryServiceImplIntegrationTest {
@Autowired
@Qualifier("com.joostschouten.businessadmin.api.rs.RSTimeEntryService.proxy")
protected RSEntryService proxy;
@Test
public void testGetSummedEntries() throws Exception {
ApiDateRangeFilter dateRangeFilter = new ApiDateRangeFilter();
dateRangeFilter.setStart(new DateTime().minusDays(20));
dateRangeFilter.setEnd(new DateTime().plusDays(10));
ApiEntries summedEntries = proxy.getSummedTimeEntries(dateRangeFilter);//exception on this line
}
Комментарии:
1. Побочное замечание — если вы настроите CXF на использование Jackson для обработки JSON / XML, вы можете включить модуль joda Джексона, который обрабатывает классы времени joda.
2. @AlexeyGavrilov Спасибо, приятно знать! Хотя для других типов данных я все равно хотел бы сделать эту работу.
3. Когда-нибудь это работало? На данный момент у меня точно такая же проблема с аналогичной настройкой swagger / cxf.
4. К сожалению, у меня это не сработало, и в конце концов я изменил свой ApiDateRangeFilter на использование String для хранения дат и выполнения де-серилизации в моем собственном коде. Через несколько дней мне просто нужно было, чтобы он работал;-) Извините, у меня нет лучшего ответа. Удачи!
5. Этот код работает для меня с CXF 3.0.3 и создан вручную
JAXRSServerFactoryBean
, сParamConverterProviderImpl
добавлением usingfactory.setProviders(…)
.