【问题标题】:Glassfish XML (or JSON) Response for JAX-RS Object Marshalling Results in HTTP 500 Internal Server Error用于 JAX-RS 对象编组的 Glassfish XML(或 JSON)响应导致 HTTP 500 内部服务器错误
【发布时间】:2015-06-18 05:39:47
【问题描述】:

我正在尝试获取 JAX RS 资源以返回带有 JSON 对象的响应。当我通过资源类中的 println() 调用显示响应属性时,我看到 MediaType 已正确设置为“application/json”,有一个实体与响应相关联,具有预期的类型 (SalesOrder)、状态 (Status .FOUND) 并且响应对象是 OutboundJaxrsResponse 的一个实例。但不知何故,当浏览器(或 Jersey 客户端)收到响应时,这些响应属性似乎被“替换”,结果是 HTTP 500 内部服务器错误。我的 SalesOrder 类使用 @XmlRootElement 进行注释。

我的资源如下所示:

@GET
@Path("{orderUid}")
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public Response getSalesOrder(@PathParam("orderUid") Integer orderUid) {
    Response response = null;
    System.out.println("Entering SalesOrderResource getSalesOrder()...");
    SalesOrder retrievedSalesOrder =   salesOrderService.retrieveSalesOrder(orderUid);
     System.out.println("Service called and found salesOrder Uid: " + retrievedSalesOrder.getSalesOrderUid());
    if (retrievedSalesOrder != null) {
        System.out.println("SalesOrder found with UID: " + retrievedSalesOrder.getSalesOrderUid());
        response = Response.status(Status.FOUND).entity(retrievedSalesOrder).type(MediaType.APPLICATION_JSON).build();
        // The following readEntity call results in a Javax.ejb.EJBException ???
        // SalesOrder fetched = response.readEntity(SalesOrder.class);
    } else {
        response = Response.status(Status.NOT_FOUND).header("x-reason", "Order cannot be found").build();
    }
System.out.println("Response status: " + response.getStatus());
System.out.println("Response status info: " + response.getStatusInfo());
System.out.println("Response class: " + response.getClass());
System.out.println("Response length: " + response.getLength());
System.out.println("Response media type: " + response.getMediaType());
System.out.println("Response entity: " + response.getEntity());
    return response;
}

...在运行时会导致以下结果:

2015-04-12T18:08:21.803-0600|信息:响应状态:302 2015-04-12T18:08:21.803-0600|信息:响应状态信息:找到 2015-04-12T18:08:21.803-0600|信息:响应类:类 org.glassfish.jersey.message.internal.OutboundJaxrsResponse 2015-04-12T18:08:21.803-0600|信息:响应长度:-1 2015-04-12T18:08:21.803-0600|信息:响应媒体类型:应用程序/xml 2015-04-12T18:08:21.803-0600|信息:响应实体:business.salesOrderMgmt.entity.SalesOrder@5e49cadd

SalesOrder 实体定义为:

@Entity
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@JsonIgnoreProperties({"subTotal", "userAccount"})
@Table(name="sales_order")
@NamedQuery(name="SalesOrder.findAll", query="SELECT s FROM SalesOrder s")
public class SalesOrder implements Serializable {
private static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="SALES_ORDER_UID")
private int salesOrderUid;

@Column(name="ORDER_NUMBER")
private String orderNumber;

@Column(name="BILL_TO_CITY")
private String billToCity;

@Column(name="BILL_TO_FIRST_NAME")
private String billToFirstName;

@Column(name="BILL_TO_LAST_NAME")
private String billToLastName;

@Column(name="BILL_TO_STATE")
private String billToState;

@Column(name="BILL_TO_STREET_NAME")
private String billToStreetName;

@Column(name="BILL_TO_STREET_NUMBER")
private String billToStreetNumber;

@Column(name="BILL_TO_UNIT_NUMBER")
private String billToUnitNumber;

@Column(name="BILL_TO_ZIP_CODE")
private int billToZipCode;

@Column(name="CREDIT_CARD_CSV")
private int creditCardCsv;

@Temporal(TemporalType.TIMESTAMP)
@Column(name="CREDIT_CARD_EXPIRATION_DATE")
private Date creditCardExpirationDate;

@Column(name="CREDIT_CARD_NUMBER")
private String creditCardNumber;

@Column(name="CREDIT_CARD_TYPE")
private String creditCardType;

@Column(name="EMAIL_ADDRESS")
private String emailAddress;

@Column(name="NAME_ON_CREDIT_CARD")
private String nameOnCreditCard;

@Temporal(TemporalType.TIMESTAMP)
@Column(name="SALES_ORDER_DATE")
private Date salesOrderDate;

@Column(name="SALES_ORDER_STATUS")
private String salesOrderStatus;

@Column(name="SHIP_TO_CITY")
private String shipToCity;

@Column(name="SHIP_TO_STATE")
private String shipToState;

@Column(name="SHIP_TO_STREET_NAME")
private String shipToStreetName;

@Column(name="SHIP_TO_STREET_NUMBER")
private String shipToStreetNumber;

@Column(name="SHIP_TO_UNIT_NUMBER")
private String shipToUnitNumber;

@Column(name="SHIP_TO_ZIP_CODE")
private int shipToZipCode;

@Column(name="PROMO_CODE")
private String promoCode;

//Calculated and persisted for data retrieval performance
@Column(name="SUB_TOTAL")
private BigDecimal subTotal;

@Column(name="DISCOUNT")
private BigDecimal discount;

@Column(name="SALES_TAX")
private BigDecimal salesTax;

@Column(name="SHIPPING")
private BigDecimal shipping;

@Column(name="TOTAL")
private BigDecimal total;

@Version
@Column(name="LAST_UPDATED_TIME")
private Timestamp lastUpdatedTime;

//bi-directional many-to-one association to UserAccount
@ManyToOne
@JoinColumn(name="USER_ACCOUNT_UID")
private UserAccount userAccount;

@OneToMany(targetEntity=SalesOrderLine.class, mappedBy = "salesOrder", cascade = CascadeType.ALL)
private List<SalesOrderLine> lineItems;

public SalesOrder() {
}

...getter 和 setter

我的 POM 中的依赖项包括:

    <dependency>
        <groupId>javax.ws.rs</groupId>
        <artifactId>javax.ws.rs-api</artifactId>
        <version>2.0.1</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-annotations</artifactId>
        <version>2.5.2</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.5.2</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.module</groupId>
        <artifactId>jackson-module-jaxb-annotations</artifactId>
        <version>2.5.2</version>
    </dependency>

不仅请求 (http://localhost:8080/[myapp]/resources/salesOrders/13) 会导致 HTTP 500 内部服务器错误,而且当我尝试在资源中调用 response.readEntity(SalesOrder.class) 时,Glassfish 服务器日志会显示 javax.ejb.EJBException 警告由 java.lang.IllegalStateException 引起:org.glassfish.jersey.message.internal.OutboundJaxrsResponse.readEntity(OutboundJaxrsResponse.java:145) 的出站消息不支持方法。

我认为 SalesOrder 对象的 JAXB 编组存在问题,但我无法确定根本原因。如果我只是尝试以下操作,我仍然会收到 HTTP 500 Internal Server 错误,这表明 XML 和 JSON 编组都没有发生,但我认为这是内置在最新版本中的(Glassfish 4、JAX-RS 2)?

有什么想法吗?

【问题讨论】:

  • 您是否尝试过将请求类型设置为 JSON? request.type(MediaType.APPLICATION_JSON).post(json, String.class);?顺便说一句,你的代码在很多地方都是一团糟。
  • 仅供参考,这些 Jackson 依赖项不会用作 JAX-RS 编组器。您需要 Jackson 的 JAX-RS 提供者,而不仅仅是 Jackson 本身。 MOXy 是 Glassfish 的默认设置,它最有可能用于您的情况。如果要使用Jackson,需要添加Jackson provider,并注册JacksonFeature,以便禁用MOXy。

标签: json jaxb glassfish


【解决方案1】:

我发现了问题并将其发布在此处以供他人使用。 1)我在资源方法中添加了以下内容: @Consumes(MediaType.TEXT_PLAIN) 2)步骤#1在运行时导致以下错误: 在对象图中检测到循环。这将导致无限深的 XML 3) 该错误导致我将@XmlTransient 添加到与OneToMany、ManyToMany 和ManyToOne 中的其他实体相关的所有实体字段中。

现在我可以返回 XML 和 JSON 格式的响应了。

【讨论】:

    【解决方案2】:

    我也遇到过类似的问题。可以肯定的是,请检查您的日志是否显示如下内容:

    严重:找不到媒体类型 = 应用程序/json 的 MessageBodyWriter, type=class SalesOrder, genericType=class SalesOrder。

    如果是这样,问题是您没有注册 Jackson(或其他 JSON 编写器提供程序)。有关说明,请参阅 Jersey 文档的这一部分:

    https://jersey.java.net/documentation/latest/media.html#d0e7857

    就我而言,我选择了杰克逊。我在 pom.xml 中添加了以下内容。

    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.5.2</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.jaxrs</groupId>
      <artifactId>jackson-jaxrs-json-provider</artifactId>
      <version>2.5.2</version>
    </dependency>
    <dependency>
      <groupId>org.glassfish.jersey.media</groupId>
      <artifactId>jersey-media-json-jackson</artifactId>
      <version>2.17</version>
    </dependency>
    

    然后我必须注册提供者:

    public class Application extends ResourceConfig {
        public Application() {
            packages(<your ws package>);
            register(JacksonFeature.class);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-01
      • 2013-11-02
      • 2015-03-24
      • 1970-01-01
      • 2019-01-03
      • 2013-08-11
      相关资源
      最近更新 更多