2012-10-14 4 views
14

私は現時点でジャージーを試していますが、次にthisというリンクがあり、netbeansでWebサービスを設定しています。私はエンティティクラスと私のRESTクラスを持っています。 javafx2クライアントからオブジェクト(この場合はUsersオブジェクト)の追加、編集、削除、要求を行います。ジャージーメディアタイプの競合が発生しました

しかし、私はいくつかの簡単な認証のために私のwebserviceに新しいメソッドを追加しようとしています。

@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(); 
} 
:私は(Netbeansの7.2によって生成された)私のUsersFacadeREST.javaファイルに次のコードを追加しました。その後

@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") 
}) 

:まず私はUsers.javaファイルに新しい名前付きクエリ(Users.login)を追加しました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 

私はこれに新たなんだと、私はlogin()メソッドは、findRange(との競合を与えているのはなぜか見当もつかない)?最初は2つの文字列パラメータを持ち、Usersオブジェクトを与え、2番目のパラメータは2つの整数パラメータを持ち、Listオブジェクトを返します。スーパークラスの

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

:私はつもりは私のWebサービスに追加され、いくつかのカスタムクエリが必要だとして、この問題を解決する方法...完了のために

はあります

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に一致するパステンプレートを使用していることです。 は"{c}/{d}"に相当します - 同じように"{username}/{password}""{from}/{to}"に相当します。両方の方法とも同じメディアタイプを使用するため、あいまいさがあります。これを修正するには、パステンプレートの正規表現を使用して、より具体的にすることができます。私。 "{from}/{to}"は常に数字である必要があるため、次のように変更することで明確にすることができます:"{from: [0-9]+}/{to: [0-9]+}"

とにかく、ユーザー名とパスワードからプレーンナンバーを選択することはできませんか?あなたの場合のように、2つのリソースのそれぞれに異なるURI「サブスペース」を使用するほうがずっと良いでしょう。例:login/{username}/{password}およびranges/{from}/{to}設計上の

しかし、いくつかのポイント:

  1. URIでパスワードを入れて非常に悪い考えです。決してそれをしないでください!既存の実績のある認証スキームを見てください。ホイールを再構築しようとしないでください。
  2. クエリパラメータを使用して範囲を指定することを検討してください。コレクションのリソース(「myapp.com/calendar/events」など)がある場合は、クエリパラメータを使用して範囲をモデル化できます。 "myapp.com/calendar/events?from=xxx & to = yyy
+0

私の最初の点については、 rs webserviceでもまだ見つけられていませんあなたは何か知っていますか?第2のポイントについては、私はユーザーのコレクションが必要ですが、私は別のコレクションを与える異なる名前のクエリを持っています。アクセスレベル、...)クエリパラメータを操作して、どのクエリを実行するかをメソッドに知らせるのは良い解決策ですか?たとえばmyapp.com/calendar/events?qry = byCountryまたはqry = byAccessLevel – Perneel

+1

1)最も簡単な方法は、HTTP BASIC認証を使用することです。 SSL(HTTPS)を使用して - グーグルで試してみてください。 2)はい、クエリパラメータにフィルタを指定しても問題ありません。 –

+0

素晴らしい、ありがとうございました。 – Perneel

関連する問題