2012-10-14 17 views
14

Sto provando Jersey al momento, seguito dal collegamento this per impostare un servizio Web in netbeans. Ho le mie classi di entità e le mie lezioni di REST. Funziona per aggiungere, modificare, cancellare, richiedere oggetti (in questo caso oggetti utente) da un client javafx2.Jersey Produzione del tipo di conflitto in conflitto

Tuttavia, ora provo ad aggiungere un nuovo metodo al mio webservice per alcune semplici autenticazione. In primo luogo ho aggiunto una nuova query denominata (Users.login) nel file Users.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") 
}) 

In seguito ho aggiunto seguente codice al mio file UsersFacadeREST.java (generato da 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(); 
} 

Tuttavia, ricevo seguente errore quando si cerca di distribuire il servizio 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 

Come io sono nuovo a questo, non ho alcun indizio perché il metodo di login() sta dando un conflitto con findRange()? Il primo ha 2 parametri di stringa e fornisce un oggetto Users, il secondo ha 2 parametri interi e restituisce un oggetto List? C'è un modo per risolvere questo problema, come mi servira alcune query personalizzate aggiunte al mio webservice ...

di esecuzione:

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

Codice in classe super (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(); 
} 

risposta

24

Il problema è che entrambi i metodi utilizzano modelli di percorso che corrispondono agli stessi URI. "{a}/{b}" equivale a "{c}/{d}" - nello stesso modo "{username}/{password}" equivale a "{from}/{to}". E poiché entrambi i metodi usano lo stesso tipo di media, c'è un'ambiguità. È possibile risolvere questo problema utilizzando un'espressione regolare nel modello di percorso per renderlo più specifico. Cioè poiché "{from}/{to}" dovrebbe sempre essere numeri, puoi disambigerlo modificandolo come segue: "{from: [0-9]+}/{to: [0-9]+}".

In ogni caso, sei sicuro che nessun utente selezionerà numeri semplici da nome utente e password? Sembra che nel tuo caso sarebbe molto meglio usare "spazio secondario" URI diverso per ciascuna delle due risorse. Ad es .: login/{username}/{password} e ranges/{from}/{to}.

MA, alcuni punti sul disegno:

  1. È un pessima idea di mettere le password nel URI. Mai e poi mai farlo! Guarda alcuni schemi di autenticazione provati esistenti: non provare a reinventare la ruota.
  2. Considerare l'utilizzo dei parametri di query per specificare gli intervalli, ad es. se disponi di una risorsa di raccolta (come "myapp.com/calendar/events") puoi modellare gli intervalli utilizzando i parametri di query, ad es. "Myapp.com/calendar/events?from=xxx & a = yyy.
+0

Grazie per la risposta Martin! Informazioni sul primo punto, ho cercato per alcuni esempi di accesso da un client Java per un JAX- rs webservice ma non è stato ancora in grado di trovarne uno. Ne conosci qualcuno? Per quanto riguarda il secondo punto, ad esempio voglio una raccolta di utenti ma ho query con nome diverse che daranno una collezione diversa (Utenti filtrati per Paese, Utenti filtrati da livello di accesso, ...) È una buona soluzione quindi lavorare con i parametri di query per far sapere al metodo quale query deve essere eseguita? Eg myapp.com/calendar/events?qry = byCountry o qry = byAccessLevel – Perneel

+1

1) il modo più semplice sarebbe utilizzare l'autenticazione HTTP BASIC. con SSL (HTTPS) - prova googling per quello. 2) sì, va bene specificare i filtri nei parametri di query –

+0

Superbo, grazie mille per il tuo tempo Martin! – Perneel