2012-10-14 43 views
14

我現在正在嘗試澤西,後面的this鏈接在netbeans中建立一個web服務。我有我的實體類和我的REST類。 它用於從javafx2客戶端添加,編輯,刪除請求對象(本例中爲用戶對象)。澤西生產媒體類型衝突

但是,現在我嘗試添加一個新的方法到我的web服務進行一些簡單的身份驗證。首先我加在Users.java文件中的新命名查詢(Users.login):

@NamedQueries({ 
    @NamedQuery(name = "Users.findAll", query = "SELECT u FROM Users u"), 
    @NamedQuery(name = "Users.login", query = "SELECT u FROM Users u WHERE u.username = :username AND u.password = :password"), 
    @NamedQuery(name = "Users.findById", query = "SELECT u FROM Users u WHERE u.id = :id"), 
    @NamedQuery(name = "Users.findByUserlevel", query = "SELECT u FROM Users u WHERE u.userlevel = :userlevel"), 
    @NamedQuery(name = "Users.findByDisabled", query = "SELECT u FROM Users u WHERE u.disabled = :disabled") 
}) 

後來我添加以下代碼到我的UsersFacadeREST.java文件(Netbeans的7.2生成):

@GET 
@Path("{username}/{password}") 
@Produces({"application/xml", "application/json"}) 
public Users login(@PathParam("username") String username, @PathParam("password") String password) { 
    return em.createNamedQuery("login", Users.class) 
      .setParameter("username", username) 
      .setParameter("password", password) 
      .getSingleResult(); 
} 

然而,試圖部署Web服務時,我收到以下錯誤:由於我是新來的這

SEVERE: Producing media type conflict. The resource methods public entities.Users service.UsersFacadeREST.login(java.lang.String,java.lang.String) and public java.util.List service.UsersFacadeREST.findRange(java.lang.Integer,java.lang.Integer) can produce the same media type 

,我不知道爲什麼登錄()方法是給有findRange衝突()?第一個有2個String參數並給出一個Users對象,第二個有2個整型參數並返回一個List對象?有沒有辦法爲我會需要添加到我的web服務的一些自定義查詢來解決這個問題...

完成:

@GET 
@Path("{from}/{to}") 
@Produces({"application/xml", "application/json"}) 
public List<Users> findRange(@PathParam("from") Integer from, @PathParam("to") Integer to) { 
    return super.findRange(new int[]{from, to}); 
} 

代碼在超類(AbstractFacade.java)

public List<T> findRange(int[] range) { 
    javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery(); 
    cq.select(cq.from(entityClass)); 
    javax.persistence.Query q = getEntityManager().createQuery(cq); 
    q.setMaxResults(range[1] - range[0]); 
    q.setFirstResult(range[0]); 
    return q.getResultList(); 
} 

回答

24

問題是,兩種方法都使用匹配相同URI的路徑模板。 "{a}/{b}"相當於"{c}/{d}" - 同樣"{username}/{password}"相當於"{from}/{to}"。而且由於這兩種方法也使用相同的媒體類型,所以存在歧義。您可以通過在路徑模板中使用正則表達式來解決此問題,以使其更具體。即因爲"{from}/{to}"應該始終是數字,您可以通過如下更改它來消除歧義:"{from: [0-9]+}/{to: [0-9]+}"

無論如何,你確定沒有用戶會從用戶名和密碼中挑選普通數字嗎?看起來就像在你的情況下,爲兩個資源中的每一個使用不同的URI「子空間」會更好。例如:login/{username}/{password}ranges/{from}/{to}

,但在設計上幾點:

  1. 這是一個非常糟糕主意,把密碼中的URI。永遠不要做!看看現有的一些經過驗證的認證方案 - 不要試圖重新發明輪子。
  2. 考慮使用查詢參數來指定範圍 - 例如,如果您有一些收集資源(如「myapp.com/calendar/events」),則可以使用查詢參數對模型範圍進行建模 - 例如, 「myapp.com/calendar/events?from=xxx & to = yyy
+0

感謝您的回答Martin!關於您的第一點,我一直在尋找一些從java客戶端到jax-關於第二點,例如我想要一個用戶集合,但是我有不同的命名查詢,它們會給出不同的集合(用戶按國家/地區過濾,用戶經過篩選)訪問級別,...)這是一個很好的解決方案,然後使用查詢參數讓該方法知道應該執行哪個查詢?例如myapp.com/calendar/events?qry = byCountry或qry = byAccessLevel – Perneel

+1

1)最簡單的方法是使用HTTP BASIC身份驗證。與SSL(HTTPS) - 嘗試谷歌搜索。 2)是的,可以在查詢參數中指定過濾器 –

+0

非常棒,非常感謝您的時間Martin! – Perneel

相關問題