我试图获取JAX RS资源以返回带有JSON对象的响应。当我通过资源类中的println()调用显示响应属性时,我发现MediaType已正确设置为“application/json”,并且存在与具有预期类型(SalesOrder),状态.FOUND),并且响应对象是OutboundJaxrsResponse的一个实例。但是,不管怎样,当浏览器(或Jersey客户端)收到响应时,这些响应属性似乎会被“替换”,并导致HTTP 500内部服务器错误。我的SalesOrder类用@XmlRootElement注释。Glassfish XML(或JSON)对HTTP 500内部服务器中的JAX-RS对象编组结果的响应错误
我的资源是这样的:
@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 |信息:响应类: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 |信息:响应实体:[email protected]
的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服务器日志显示由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)中的?
任何想法?
您是否尝试过将请求类型设置为JSON? 'request.type(MediaType.APPLICATION_JSON).post(json,String.class);'?顺便说一下,你的代码在很多地方都是一团糟。 –
仅供参考,那些杰克逊依赖不会被用作JAX-RS编组。你需要一个杰克逊的JAX-RS提供者,而不仅仅是杰克逊本身。 MOXY是Glassfish的默认设置,它很可能用于您的案例。如果你想使用Jackson,你需要添加[Jackson provider](https://jersey.java.net/documentation/latest/media.html#json.jackson),并注册'JacksonFeature',这样可以禁用MOXy 。 –