Как настроить Jsonp и CXF с перехватчиками

Я разрабатываю спокойный WS и хочу дать пользователям возможность забирать данные из моего WS в виде XML или Json, а также иметь возможность выбирать функцию обратного вызова, если они хотят Jsonp. Это то, что у меня есть до сих пор, и часть с перехватчиками основана на CXF – JAX-RS: привязки данных.

Моя служба отдыха:

@GET
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@Produces({ "application/x-javascript", MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public Response getServers(@Context ServletContext context,
        @Context Request request,
        @QueryParam("format") String format,
        @QueryParam("callback") String callback) {

some code where server object is created....

    if(format.equals("json"){

        if(callback!= null){
            response = Response.status(Status.OK).type("application/x-javascript")
                        .entity(server).build();
        }else{
            response = Response.status(Status.OK).type("application/json")
                        .entity(server).build();
        }

    } else {
    response = Response.status(Status.OK).type("application/xml")
                        .entity(server).build();
    }
    return response;
}

Мой серверный объект:

@XmlRootElement (name="Server")
public class Server implements Serializable {

    private String name=null;
    private String hardware = null;

    public Server(){

    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getHardware() {
        return hardware;
    }

    public void setHardware(String hardware) {
        this.hardware = hardware;
    }

}

Мой beans.xml в WEB-INF:

<?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:jaxrs="http://cxf.apache.org/jaxrs"
  xmlns:context="http://www.springframework.org/schema/context"
  xsi:schemaLocation="
http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://cxf.apache.org/jaxrs
http://cxf.apache.org/schemas/jaxrs.xsd">

  <import resource="classpath:META-INF/cxf/cxf.xml" />

  <context:property-placeholder/>
  <context:annotation-config/>
  <bean class="org.springframework.web.context.support.ServletContextPropertyPlaceholderConfigurer"/>
  <bean class="org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer"/>

   <jaxrs:server id="services" address="/">
    <jaxrs:serviceBeans>
      <bean class="com.ba.serversws_cxf.resources.MyResource" />
    </jaxrs:serviceBeans>

    <jaxrs:inInterceptors>
       <bean class="org.apache.cxf.jaxrs.provider.jsonp.JsonpInInterceptor">
        <property name="callbackParam" value="callback"/>
       </bean>
    </jaxrs:inInterceptors>
    <jaxrs:outInterceptors>
       <bean class="org.apache.cxf.jaxrs.provider.jsonp.JsonpPreStreamInterceptor">
            <property name="mediaType" value="application/x+javascript"/>
       </bean>
       <bean class="org.apache.cxf.jaxrs.provider.jsonp.JsonpPostStreamInterceptor"/>
    </jaxrs:outInterceptors>

    <jaxrs:providers>
        <bean class="org.codehaus.jackson.jaxrs.JacksonJsonProvider"/>
    </jaxrs:providers>
    </jaxrs:server>

</beans>

Ошибка, которую я получаю, когда я устанавливаю параметр запроса "обратный вызов":

org.apache.cxf.jaxrs.interceptor.JAXRSOutInterceptor writeResponseErrorMessage
WARNING: No message body writer has been found for response class Server.

Он отлично работает для других двух других случаев.

Я искал, чтобы найти решение, но до сих пор ничего.

Любые идеи?

Спасибо


person NikosDim    schedule 07.06.2013    source источник
comment
Мне до сих пор не удалось заставить работать перехватчики, но удалось получить jsonp, расширив методы org.apache.cxf.jaxrs.provider.json.JSONProvider и @Overriding метода writeTo(), как показано здесь   -  person NikosDim    schedule 17.06.2013
comment
Можете ли вы опубликовать свой ответ здесь?   -  person Bhuvan    schedule 28.06.2013


Ответы (1)


Вот мой класс, который @Overrides метод wrtieTo() метода org.apache.cxf.jaxrs.provider.json.JSONProvider;

Прежде всего, в моем файле beans.xml я использовал <jaxrs:extensionMappings> и объявил расширение jsonp.

Вот код

<jaxrs:server id="services" address="/">
   <jaxrs:extensionMappings>
      <entry key="xml" value="application/xml" />
      <entry key="json" value="application/json" />
      <entry key="jsonp" value="application/javascript"/>
   </jaxrs:extensionMappings>
</jaxrs:server>

А ниже мой код метода writeTo(), который у меня есть @Override

import java.io.IOException;
import java.io.OutputStream;

import java.lang.annotation.Annotation;
import java.lang.reflect.Type;

import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;

import org.apache.cxf.jaxrs.provider.json.JSONProvider;
import org.apache.cxf.jaxrs.utils.HttpUtils;

@SuppressWarnings("rawtypes")
@Produces("application/javascript")
public class JsonpProvider extends JSONProvider {


    @SuppressWarnings("unchecked")
    @Override
    public void writeTo(Object obj, Class cls, Type genericType,
            Annotation[] anns, MediaType m, MultivaluedMap headers,
            OutputStream os) throws IOException {

        String requestURI = getContext().getHttpServletRequest()
                .getRequestURI();
        if (requestURI.contains(".jsonp")) {
            String prefix = getContext().getHttpServletRequest().getParameter(
                    "_jsonp");
            if (prefix != null && !prefix.isEmpty()) {
                os.write(prefix.getBytes(HttpUtils.getSetEncoding(m, headers,
                        "UTF-8")));
            } else {
                os.write("callback".getBytes(HttpUtils.getSetEncoding(m,
                        headers, "UTF-8")));
            }
            os.write('(');
            super.writeTo(obj, cls, genericType, anns, m, headers, os);
            os.write(')');
        } else {
            super.writeTo(obj, cls, genericType, anns, m, headers, os);
        }
    }
}

Итак, что я делаю в приведенном выше коде, так это проверяю, было ли расширение .jsonp указано для URL-адреса. Если да, то я знаю, что должен вернуть jsopn с функцией обратного вызова. Последнее, что нужно сделать, это установить имя функции обратного вызова. Если пользователь установил для параметра запроса _jsonp URL-адрес, значением этого параметра будет имя функции обратного вызова. Если параметр _jsonp pquery равен нулю, я ставлю имя по умолчанию callback.

И, конечно же, в файле beans.xml в качестве поставщика json вы указали JsonpProvider выше:

<jaxrs:providers>
   <bean class="org.apache.cxf.jaxrs.ext.search.SearchContextProvider"/>
   <bean class="com.ba.serversws_cxf.utils.JsonpProvider">
      <property name="ignoreNamespaces" value="true" />
      <property name="dropRootElement" value="false" />
      <property name="supportUnwrapped" value="true" />
   </bean>
</jaxrs:providers>

Надеюсь, это поможет @bhuvan!

person NikosDim    schedule 28.06.2013