Настройка CXF JAX-RS на основе прокси API для преобразования объектов @FormParam в JSON - PullRequest
1 голос
/ 25 мая 2011

Быстрое обобщение проблемы:

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


Я создал несколько служб в Apache CXF JAX-RS, которые принимают несколько потенциально сложных объектов в качестве аргументов.Реализуя valueOf (String s) для сложных bean-компонентов, я могу передать несколько «закодированных» 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=123&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, которая каким-то волшебным образом заменит метод toString объектов на JSON?Как и в String toString () {вернуть новый ObjectMapper.writeValueAsString (this);}

...