2014-02-19 39 views
3

我正在開發一個Web服務使用JAX-RS API澤西島1.17作爲我的實現。澤西島產生意外的默認媒體類型時拋出WebApplicationException

我希望客戶端可以選擇使用Accept HTTP標頭指定的JSON和XML。當客戶端在請求中不包含Accept標頭時,我希望JSON成爲默認值。我試圖通過在MediaType.APPLICATION_XML之前將MediaType.APPLICATION_JSON置於Produces註釋中來實現此目的。

這似乎是在正常情況下工作:

$ curl 'http://localhost:8080/webservice/Bob' 
{"text":"Hello, Bob"} 

$ curl -H'Accept: application/json' 'http://localhost:8080/webservice/Bob' 
{"text":"Hello, Bob"} 

$ curl -H'Accept: application/xml' 'http://localhost:8080/webservice/Bob' 
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Greeting text="Hello, Bob"/> 

但是,如果我把一個WebApplicationException從我的資源類的構造函數,響應媒體類型默認爲XML:

$ curl 'http://localhost:8080/webservice/Vader' 
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Error message="Illegal name"/> 

如果客戶端包含Accept標頭,媒體類型正確:

$ curl -H'Accept: application/json' 'http://localhost:8080/webservice/Vader' 
{"message":"Illegal name"} 

即使對於從資源類構造函數中引發的錯誤,我如何配置Jersey以使用默認值?

這裏是我的資源類(full example on GitHub)代碼:

package org.example.errorhandling; 

import javax.ws.rs.GET; 
import javax.ws.rs.Path; 
import javax.ws.rs.PathParam; 
import javax.ws.rs.Produces; 
import javax.ws.rs.WebApplicationException; 
import javax.ws.rs.core.MediaType; 
import javax.ws.rs.core.Response; 
import javax.ws.rs.core.Response.Status; 

import org.example.errorhandling.repr.Error; 
import org.example.errorhandling.repr.Greeting; 

@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) 
@Path("/{name}") 
public class Greeter { 
    private final String name; 

    public Greeter(@PathParam("name") String name) { 
     if ("Vader".equals(name)) { 
      Error error = new Error(); 
      error.message = "Illegal name"; 
      Response errorResponse = Response.status(Status.BAD_REQUEST).entity(error).build(); 
      throw new WebApplicationException(errorResponse); 
     } else { 
      this.name = name; 
     } 
    } 

    @GET 
    public Response greet() { 
     Greeting greeting = new Greeting(); 
     greeting.text = "Hello, " + name; 
     return Response.ok(greeting).build(); 
    } 
} 
+1

爲什麼你使用構造函數,而不是'greet'方法來接收'@PathParam(「名稱」)'? – 2014-02-20 07:51:38

+0

@LutzHorn在我真正的web服務中,我在構造函數中捕獲了@PathParam(「name」),以便公開一些子資源。在我的構造函數中,我在後端系統中查找由'name'標識的對象,並且如果查找失敗,我想立即拋出異常。 – glerup

回答

0

此問題有一個解決方法,由於suggestionusul_

解決方法是使用selectVariant()機制以編程方式選擇與請求中的Accept標頭相匹配的介質類型。這使得有可能以重複首選訂單爲代價執行默認媒體類型。

這裏的構造函數修改爲使用這種技術(full code on GitHub):

public Greeter(@PathParam("name") String name, @Context Request request) { 
    if ("Vader".equals(name)) { 
     Error error = new Error(); 
     error.message = "Illegal name"; 
     List<Variant> variants = Variant.mediaTypes(MediaType.APPLICATION_JSON_TYPE, MediaType.APPLICATION_XML_TYPE).add().build(); 
     Variant variant = request.selectVariant(variants); 
     Response errorResponse = Response.status(Status.BAD_REQUEST).entity(error).variant(variant).build(); 
     throw new WebApplicationException(errorResponse); 
    } else { 
     this.name = name; 
    } 
} 
0
+0

我只是試圖使用異常映射器([GitHub上的代碼](https://github.com/glerup/jersey-error-handling-sample-app/tree/experiment/error-mapping))。但行爲是一樣的,資源的媒體類型順序似乎被忽略。 – glerup

+0

有了這個,你有一個響應,所以你可以設置響應類型 –

+0

你的意思是我應該聲明'@HeaderParam(「Accept」)'並嘗試自己解釋'Accept'頭?這聽起來像一個黑客。 JAX-RS的實現應該爲我做到這一點。 – glerup