Glassfish XML(或JSON)对HTTP 500内部服务器错误中的JAX-RS对象编组结果的响应 [英] Glassfish XML (or JSON) Response for JAX-RS Object Marshalling Results in HTTP 500 Internal Server Error

查看:129
本文介绍了Glassfish XML(或JSON)对HTTP 500内部服务器错误中的JAX-RS对象编组结果的响应的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图让JAX RS资源返回一个带有JSON对象的响应。当我通过资源类中的println()调用显示响应属性时,我发现MediaType已正确设置为application / json,并且存在与具有预期类型(SalesOrder),状态.FOUND),并且响应对象是OutboundJaxrsResponse的一个实例。但某种程度上,当浏览器(或Jersey客户端)收到响应时,这些响应属性似乎会被替换,并导致HTTP 500内部服务器错误。我的SalesOrder类用@XmlRootElement注释。



我的资源如下所示:

  @GET 
@Path({orderUid})
@Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
public Response getSalesOrder(@PathParam(orderUid)Integer orderUid){
响应响应=空;
System.out.println(输入SalesOrderResource getSalesOrder()...);
SalesOrder retrieveSalesOrder = salesOrderService.retrieveSalesOrder(orderUid);
System.out.println(Service called and found salesOrder Uid:+ retrieveSalesOrder.getSalesOrderUid());
if(retrieveSalesOrder!= null){
System.out.println(SalesOrder found with UID:+ retrieveSalesOrder.getSalesOrderUid());
response = Response.status(Status.FOUND).entity(retrieveSalesOrder).type(MediaType.APPLICATION_JSON).build();
//以下readEntity调用导致Javax.ejb.EJBException ???
// SalesOrder fetched = response.readEntity(SalesOrder.class);
} else {
response = Response.status(Status.NOT_FOUND).header(x-reason,Order can not 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());
返回响应;
}

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



2015-04-12T18:08:21.803-0600 |信息:回复状态:302
2015-04-12T18:08:21.803-0600 |信息:回复状态信息:发现
2015-04-12T18:08:21.803-0600 |信息:回复class:class org.glassfish.jersey.message.internal.OutboundJaxrsResponse
2015-04-12T18:08:21.803-0600 |信息:响应长度:-1
2015-04-12T18:08:21.803-0600 |信息:响应媒体类型:application / xml
2015-04-12T18:08:21.803-0600 |信息:响应实体:business.salesOrderMgmt.entity.SalesOrder@5e49cadd



SalesOrder实体定义为:

<$ p $ ($code> @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 l ong 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日期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)
私人日期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;

//计算并保存数据检索性能
@Column(name =SUB_TOTAL)
private BigDecimal subTotal;

@Column(name =DISCOUNT)
私人BigDecimal折扣;

@Column(name =SALES_TAX)
private BigDecimal salesTax;

@Column(name =SHIPPING)
私人BigDecimal航运;

@Column(name =TOTAL)
私人BigDecimal总数;

@Version
@Column(name =LAST_UPDATED_TIME)
私人时间戳lastUpdatedTime;

//与UserAccount的双向多对一关联
@ManyToOne
@JoinColumn(name =USER_ACCOUNT_UID)
private UserAccount userAccount;

@OneToMany(targetEntity = SalesOrderLine.class,mappedBy =salesOrder,cascade = CascadeType.ALL)
private List< SalesOrderLine>了LineItem;
$ b $ public SalesOrder(){
}

... getters和setter

我的POM中的依赖包括:

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

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



我认为SalesOrder对象的JAXB编组存在问题,但我无法确定根本原因。如果我简单地尝试以下操作,我仍然会收到HTTP 500内部服务器错误,指出XML和JSON编组都不会发生,但我认为这是内置到最新版本(GlassFish 4,JAX-RS 2)中的?



有什么想法?

解决方案

张贴在这里为了他人的利益。
1)我在资源方法中添加了以下内容:
@Consumes(MediaType.TEXT_PLAIN)
2)步骤1在运行时导致以下错误:
循环是在对象图中检测到。这将导致无限深的XML
3)错误导致我将@XmlTransient添加到与OneToMany,ManyToMany和ManyToOne中的其他实体相关的所有实体字段中。



现在我能够返回XML和JSON响应。


I am trying to get a JAX RS resource to return a response with a JSON object. When I display the response properties via println() calls in the resource class I see that the MediaType is correctly set to "application/json", that there is an entity associated with the response with the expected type (SalesOrder), status (Status.FOUND) and that the response object is an instance of OutboundJaxrsResponse. But somehow when the browser (or a Jersey client) receives the response, these response attributes seem to be "replaced" and a HTTP 500 Internal Server error is the result. My SalesOrder class is annotated with @XmlRootElement.

My resource looks like this:

@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;
}

...which results in the following at runtime:

2015-04-12T18:08:21.803-0600|Info: Response status: 302 2015-04-12T18:08:21.803-0600|Info: Response status info: Found 2015-04-12T18:08:21.803-0600|Info: Response class: class org.glassfish.jersey.message.internal.OutboundJaxrsResponse 2015-04-12T18:08:21.803-0600|Info: Response length: -1 2015-04-12T18:08:21.803-0600|Info: Response media type: application/xml 2015-04-12T18:08:21.803-0600|Info: Response entity: business.salesOrderMgmt.entity.SalesOrder@5e49cadd

The SalesOrder entity is defined as:

@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() {
}

...getters and setters

Dependencies in my POM include:

    <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>

Not only does a request (http://localhost:8080/[myapp]/resources/salesOrders/13) result in an HTTP 500 Internal Server error but when I have attempted calling response.readEntity(SalesOrder.class) within the resource the Glassfish server log show a javax.ejb.EJBException warning caused by java.lang.IllegalStateException: Method not supported on an outbound message at org.glassfish.jersey.message.internal.OutboundJaxrsResponse.readEntity(OutboundJaxrsResponse.java:145).

I think there is a problem with the JAXB marshalling of the SalesOrder object but I cannot pin down the root cause. If I simply attempt the following I still get an HTTP 500 Internal Server error as well, indicating that neither XML nor JSON marshalling is taking place but I thought this was built into the latest versions (Glassfish 4, JAX-RS 2)?

Any ideas?

解决方案

I figured out the problem and will post it here for the benefit of others. 1) I added the following to the resource method: @Consumes(MediaType.TEXT_PLAIN) 2) Step #1 resulted in the following error at runtime: A cycle is detected in the object graph. This will cause infinitely deep XML 3) The error led me to add @XmlTransient to all entity fields related to other entities in OneToMany, ManyToMany and ManyToOne.

Now I am able to return a response in XML and JSON.

这篇关于Glassfish XML(或JSON)对HTTP 500内部服务器错误中的JAX-RS对象编组结果的响应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆