2013-12-16 5 views
4

최근 Jersey-CXF에서 JAX-RS 응용 프로그램으로 전환했습니다. StreamingOutput을 사용하여 내 스트림을 출력했습니다. 스트림에 포함 된 데이터가 생성되기까지 ~ 20 초가 걸렸으므로 부분적으로 클라이언트에서 처리 할 수 ​​있습니다. Jersey에서는이 모든 것이 잘 작동했지만 CXF로 JAXB 빈을 반환하고 스트리밍 동작을 얻을 수 없습니다. Jersey를 사용하여 jersey.config.contentLength.buffer.server0으로 설정하고 OutputStream을 플러시하여 클라이언트에 데이터를 가져와야했지만 CXF와 동일한 것을 찾을 수 없었습니다. 나는 StreamInterceptor 예제를 기반으로 Interceptor을 작성하려했지만 모든 처리가 끝날 때까지 메소드 MessageOutputStream이 호출되지 않습니다. JAXB 빈에는 Iterator 사용자 정의가있는 Collection이 포함되어 있습니다 (사용 가능한 경우 데이터를 제공함). 디버거에서 버퍼링 된 데이터를 볼 수 있습니다.버퍼되지 않은 CXF (내용 길이 헤더 없음)

어떻게 CXF로 JAXB 빈을 스트리밍 할 수 있습니까?

답변

3

나는 Jackson과 내 자신의 MessageBodyWriter, BeanSerializerModifier 및 JsonSerializer를 사용하여 관리했습니다. XML을 사용하는 방법을 찾아야합니다.

import com.fasterxml.jackson.core.JsonGenerator; 
import com.fasterxml.jackson.core.JsonProcessingException; 
import com.fasterxml.jackson.databind.*; 
import com.fasterxml.jackson.databind.ser.BeanSerializerModifier; 
import com.fasterxml.jackson.module.jaxb.JaxbAnnotationModule; 

import javax.ws.rs.Produces; 
import javax.ws.rs.WebApplicationException; 
import javax.ws.rs.core.MediaType; 
import javax.ws.rs.core.MultivaluedMap; 
import javax.ws.rs.ext.MessageBodyWriter; 
import javax.ws.rs.ext.Provider; 
import java.io.IOException; 
import java.io.OutputStream; 
import java.lang.annotation.Annotation; 
import java.lang.reflect.Type; 

/** 
* Created by jayen on 17/12/13. 
*/ 
@SuppressWarnings({"DefaultFileTemplate"}) 
@Produces({"application/json", "application/*+json"}) 
@Provider 
public class ResponseJSONWriter implements MessageBodyWriter<Response> { 
    @Override public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) { 
     return Response.class.isAssignableFrom(type); 
    } 

    @Override 
    public long getSize(Response response, Class<?> type, Type genericType, Annotation[] annotations, 
         MediaType mediaType) { 
     return -1; 
    } 

    @Override 
    public void writeTo(Response response, Class<?> type, Type genericType, Annotation[] annotations, 
         MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) 
    throws IOException, WebApplicationException { 
     try { 
      ObjectMapper mapper = new ObjectMapper(); 
      mapper.registerModule(new JaxbAnnotationModule()); 
      mapper.setSerializerFactory(
        mapper.getSerializerFactory().withSerializerModifier(new BeanSerializerModifier() { 
         @Override 
         public JsonSerializer<?> modifySerializer(SerializationConfig config, BeanDescription beanDesc, 
                    JsonSerializer<?> serializer) { 
          return new FlushingSerializer<>(serializer); 
         } 
        })); 
      mapper.writeValue(entityStream, response); 
     } catch (Throwable e) { 
      e.printStackTrace(); 
     } 
    } 

    private class FlushingSerializer<T> extends JsonSerializer<T> { 
     private final JsonSerializer<T> serializer; 

     public FlushingSerializer(JsonSerializer<T> serializer) { 
      this.serializer = serializer; 
     } 

     @Override public void serialize(T value, JsonGenerator jgen, SerializerProvider provider) 
     throws IOException, JsonProcessingException { 
      serializer.serialize(value, jgen, provider); 
      jgen.flush(); 
     } 
    } 
}