Настройка API на основе прокси CXF JAX-RS для преобразования объектов @FormParam в JSON

#java #client-side #cxf #jax-rs

#java #на стороне клиента #cxf #jax-rs

Вопрос:

Краткое изложение проблемы:

Мне нужно каким-то образом настроить клиент JAX-RS, реализованный с использованием клиентского API на основе прокси-сервера CXF, для автоматического преобразования параметров, аннотированных с помощью @FormParam, в JSON.


Я создал несколько сервисов в Apache CXF JAX-RS, которые принимают несколько потенциально сложных объектов в качестве аргументов. Реализуя valueOf(String s) для сложных компонентов, я могу передать в «метод» несколько объектов, закодированных в формате JSON, а не только один, как это обычно бывает.

Примером реализации может быть следующее:

 @Service("receiverService")
@Path("/receiver")
public class ObjectReceiverService {
    @POST
    @Path("jsonTest")
    @Produces("application/json")
    public MyObject jsonTest(@FormParam("myPrimitive") int myPrimitive, @FormParam("myComplex") MyObject myComplex) {
        return myComplex;
    }
        ...//
}

//domain class with Mapper from Jackson
public class MyObject {
    public String foo;
    public String bar;
    public String baz;

    public static MyObject valueOf(String s) throws Exception {
        return new ObjectMapper().readValue(s, MyObject.class);
    }
        ...//implementation of equals() etc.
}
  

Это работает довольно хорошо. До сих пор я тестировал это, прибегая к низкоуровневым материалам; вручную создавая строки запроса с использованием ObjectMapper Джексона и т.д. Пример:

 //test class with lots of manual setup using WebClient
public class ObjectReceiverServiceTest {
    @Before
    public void setup() {
        ProviderFactory.getSharedInstance().registerUserProvider(new JacksonJsonProvider());
    }
    @org.junit.Test
    public void jsonTest1_recievingSameObject() throws Exception {
        String url = "http://localhost:8080/";
        String path = "rest/receiver/jsonTest";

        MyObject myObjectToSend = new MyObject();
        MyObject result = new MyObject();
        myObjectToSend.foo = "foo";
        myObjectToSend.bar = "bar";
        myObjectToSend.baz = "baz";

        WebClient client = WebClient.create(url);
        client.path(path);
        client.accept("application/json").type(MediaType.APPLICATION_FORM_URLENCODED_TYPE);
        Response r = client.post("myPrimitive=123amp;myComplex="   new ObjectMapper().writeValueAsString(myObjectToSend));

        result = new ObjectMapper().readValue(new BufferedReader(new InputStreamReader((InputStream) r.getEntity())).readLine(), MyObject.class);
        assertEquals(myObjectToSend, result);
    }
  

Что я хотел бы сделать, так это использовать API на основе прокси, как продемонстрировано в документах CXF. Это было бы намного чище и быстрее в реализации. Предыдущий тест был бы чем-то вроде

 @org.junit.Test
public void jsonTest2_recievingSameObject() throws Exception {
    String url = "http://localhost:8080/rest";
    ObjectReceiverService service = JAXRSClientFactory.create(url, ObjectReceiverService.class);

    MyObject myObjectToSend = new MyObject();
    myObjectToSend.foo = "foo2";
    myObjectToSend.bar = "bar2";
    myObjectToSend.baz = "baz2";
    MyObject result = service.jsonTest(123,myObjectToSend);

    assertEquals(myObjectToSend, result);
}
  

Сегодня это вызывает исключение WebApplicationException в org.apache.cxf.jaxrs.provider.FormEncodingProvider.writeTo(..), поскольку он, вероятно, просто ожидает примитивы.

Я не совсем уверен, как с этим бороться. Есть идеи? Возможно ли каким-либо образом создать аннотацию, скажем @JSONtoString , которая каким-то волшебным образом заменила бы метод objects toString на метод JSON? Как в String toString() { возвращает новый ObjectMapper.writeValueAsString(this); }

Комментарии:

1. Не ответ, а дополнительная информация из списка рассылки Sergey@CXF: (я): Я не совсем уверен, как с этим справиться. Есть идеи? Я попытался переопределить toString() с помощью { return new ObjectMapper.writeValueAsString(this); } , что нормально, но FormEncodingProvider.writeTo по-прежнему терпит неудачу при попытке преобразовать нестроковые объекты, такие как целое число в строку. — (Сергей:)Да, он ожидает только строки — я думаю, что исправление должно быть применено на стороне клиента до вызова FormEncodingProvider, потому что JAX-RS требует поддержки MultivaluedMap<Строка, String> —