无法使GlassFish在JAX-RS中使用我的MessageBodyWriter

时间:2014-08-27 13:49:12

标签: json rest glassfish jax-rs jersey-2.0

我需要在GlassFish 4.0中自定义JAX-RS的JSON输出。自定义MessageBodyWriter似乎很合适。我的问题是我无法做出任何例子,例如: http://blog.bdoughan.com/2012/05/moxy-as-your-jax-rs-json-provider.html,由服务器调用。我只是设置断点以查看它是否被击中。我知道它在正确的包装中等等,因为我也尝试过自定义的WriterInterceptor,并且它被击中就好了。我只需将@Provider放在正确包装中的WriterInterceptor上即可。

到目前为止我尝试过的事情:

  1. 只需使用@Provider
  2. 即可
  3. 修改web.xml并使用自定义应用程序注册自定义MOXyJsonProvider。调用应用程序类,但不调用MessageBodyWriter / MOXyJsonProvider。
  4. 添加内部类名的META-INF / services / javax.ws.rs.ext.MessageBodyWriter文件
  5. 以下是代码:

    @Provider
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    public class WebVisualizationJsonWriter extends MOXyJsonProvider {
    
    @Override
    public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
        return WebVisualizationJsonPayload.class == type
                || WebVisualizationJsonPayload.class == getDomainClass(genericType);
    }
    
    @Override
    public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
        return isReadable(type, genericType, annotations, mediaType);
    }
    
    @Override
    protected void preReadFrom(Class<Object> type, Type genericType, Annotation[] annotations, MediaType mediaType,
            MultivaluedMap<String, String> httpHeaders, Unmarshaller unmarshaller) throws JAXBException {
        unmarshaller.setProperty(MarshallerProperties.JSON_VALUE_WRAPPER, "$");
    }
    
    @Override
    protected void preWriteTo(Object object, Class<?> type, Type genericType, Annotation[] annotations,
            MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, Marshaller marshaller)
            throws JAXBException {
        marshaller.setProperty(MarshallerProperties.JSON_VALUE_WRAPPER, "$");
    }
    }
    

    在RESTful服务调用期间,没有任何上述方法被命中。

2 个答案:

答案 0 :(得分:3)

要解决此问题,必须禁用MOXy,然后启用CustomMoxyJsonProvider。

示例:

  1. 创建自己的功能,扩展javax.ws.rs.core.Feature:

    @Provider
    public class CustomMoxyFeature implements Feature {
        @Override
        public boolean configure(final FeatureContext context) {
            final String disableMoxy = CommonProperties.MOXY_JSON_FEATURE_DISABLE + '.' + context.getConfiguration().getRuntimeType().name().toLowerCase();
            context.property(disableMoxy, true);
           return true;
        }
    }
    
  2. 创建扩展MOXyJsonProvider的自己的提供程序:

    @Provider
    public class CustomMoxyJsonProvider extends MOXyJsonProvider {
        @Override
        public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
            return WebVisualizationJsonPayload.class == type
        || WebVisualizationJsonPayload.class == getDomainClass(genericType);
    }
    
        @Override
        public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
            return isReadable(type, genericType, annotations, mediaType);
    

    }

        @Override
        protected void preReadFrom(Class<Object> type, Type genericType, Annotation[] annotations, MediaType mediaType,
    MultivaluedMap<String, String> httpHeaders, Unmarshaller unmarshaller) throws JAXBException {
            unmarshaller.setProperty(MarshallerProperties.JSON_VALUE_WRAPPER, "$");
        }
    
        @Override
        protected void preWriteTo(Object object, Class<?> type, Type genericType, Annotation[] annotations,
    MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, Marshaller marshaller)
    throws JAXBException {
            marshaller.setProperty(MarshallerProperties.JSON_VALUE_WRAPPER, "$");
        }
    }
    
  3. 在应用程序配置中添加此资源:

    @javax.ws.rs.ApplicationPath("webresources")
    public class ApplicationConfig extends Application {
    
        @Override
        public Set<Class<?>> getClasses() {
            Set<Class<?>> resources = new java.util.HashSet<>();
            addRestResourceClasses(resources);
            return resources;
        }
    
        private void addRestResourceClasses(Set<Class<?>> resources) {
            resources.add(com.vinichenkosa.moxyproblem.TestResource.class);
            resources.add(com.vinichenkosa.moxyproblem.custom_provider.CustomMoxyFeature.class);
            resources.add(com.vinichenkosa.moxyproblem.custom_provider.CustomMoxyJsonProvider.class);
        }
    }
    

答案 1 :(得分:0)

自从我们升级到Glassfish 4.1后,我也遇到了同样的问题。我们还升级了我们的jersey和jax-rs依赖项(如下所示).Below是我们的自定义MessageBodyWriter,它在写入响应之前没有被调用流

 @Provider
@Produces({"application/xml", "application/vnd.jenzabar.jx-json"})
public class RestDataSourceMessageBodyWriter implements MessageBodyWriter<Object> {

  // TODO pattern is probably too simple now, was "/paged/(^[/?]+)" 
    // and didn't work with expected URL, example "/DonationGroup/findAllGroupOriginTypes/paged/0,50"
  private static final Pattern pathPattern = Pattern.compile("/paged/(.*)");

  private static final Map<Class<?>, Class<?>[]> classMap;

  private static final ReadWriteLock classMapLock;

  static {
    classMap = new HashMap<Class<?>, Class<?>[]>();
    classMapLock = new ReentrantReadWriteLock();
  }


  /*
   * Instance fields.
   */


  @Context
  private volatile ServletContext servletContext;

  @Context
  private volatile HttpServletRequest request;

  @Context
  volatile Providers providers;

  @Context
  private volatile UriInfo uriInfo;

  protected volatile Logger logger;


  /*
   * Constructors.
   */


  public RestDataSourceMessageBodyWriter() {
    super();
    this.logger = this.createLogger();
    if (this.logger == null) {
      this.logger = this.defaultCreateLogger();
    }
    assert this.logger != null;
    if (this.logger.isLoggable(Level.FINER)) {
      this.logger.log(Level.FINER, "created", this);
    }
  }


  /*
   * Instance methods.
   */


  protected Logger createLogger() {
    return this.defaultCreateLogger();
  }

  private final Logger defaultCreateLogger() {
    Class<?> c = this.getClass();
    assert c != null;
    final String className = c.getName();
    String bundleName = null;
    Logger logger = Logger.getLogger(className);
    assert logger != null;
    if (logger.isLoggable(Level.FINER)) {
      logger.entering(className, "defaultCreateLogger");
    }
    while (c != null && bundleName == null) {
      bundleName = String.format("%sLogMessages", c.getName());
      if (logger.isLoggable(Level.FINEST)) {
        logger.logp(Level.FINEST, className, "defaultCreateLogger", "Looking for a ResourceBundle with the following bundle name: {0}", bundleName);
      }
      ResourceBundle rb = null;
      try {
        rb = ResourceBundle.getBundle(bundleName);        
      } catch (final MissingResourceException noBundle) {
        if (logger.isLoggable(Level.FINEST)) {
          logger.logp(Level.FINEST, className, "defaultCreateLogger", "No ResourceBundle found for name " + bundleName, noBundle);
        }
        bundleName = null;
        rb = null;
      }
      c = c.getSuperclass();
    }
    if (bundleName != null) {
      logger = Logger.getLogger(className, bundleName);
      assert logger != null;
      if (logger.isLoggable(Level.CONFIG)) {
        logger.logp(Level.CONFIG, className, "defaultCreateLogger", "usingBundleName", bundleName);
      }
    }
    if (logger.isLoggable(Level.FINER)) {
      logger.exiting(className, "defaultCreateLogger", logger);
    }
    return logger;
  }

  @Override
  public boolean isWriteable(final Class<?> type, final Type genericType, final Annotation[] annotations, final MediaType mediaType) {
      if (this.logger.isLoggable(Level.FINER)) {
          this.logger.entering(this.getClass().getName(), "isWriteable", new Object[] { type, genericType, annotations, mediaType });
      }
      boolean returnValue = false;
      if (type != null && !RestDataSourceResponse.class.isAssignableFrom(type)) {

          if (annotations != null && annotations.length > 0) {
              for (final Annotation a : annotations) {
                  if (a instanceof Decorate) {
                      final DecorationType decorationType = ((Decorate)a).value();
                      if (decorationType != null && decorationType.equals(DecorationType.NONE)) {
                          if (this.logger.isLoggable(Level.FINER)) {
                              this.logger.exiting(this.getClass().getName(), "isWriteable", Boolean.FALSE);
                          }
                          return false;
                      }
                  }
              }
          }

          MediaType modifiedMediaType = null;
          if (mediaType.toString().equals("application/vnd.jenzabar.jx-json")) {
              modifiedMediaType = MediaType.APPLICATION_JSON_TYPE;
          } else {
              modifiedMediaType = mediaType;
          }
          final MessageBodyWriter<RestDataSourceResponse> delegate = this.providers.getMessageBodyWriter(RestDataSourceResponse.class, RestDataSourceResponse.class, annotations, modifiedMediaType);
          if (this.logger.isLoggable(Level.FINE)) {
              this.logger.logp(Level.FINE, this.getClass().getName(), "isWriteable", "usingDelegate", delegate);
          }
          returnValue = delegate != null && delegate.isWriteable(RestDataSourceResponse.class, RestDataSourceResponse.class, annotations, modifiedMediaType);
      }
      if (this.logger.isLoggable(Level.FINER)) {
          this.logger.exiting(this.getClass().getName(), "isWriteable", Boolean.valueOf(returnValue));
      }
      return returnValue;
  }