2016-03-22 10 views
0

Ich bin neu in Jersey 2 und JAX-RS, also vermisse ich wahrscheinlich etwas. Was ich versuche zu tun ist ein Testprogramm, um einen Codierungsstil bei der Entwicklung von Restdiensten zu definieren. Der Test wurde in JAVA geschrieben und verwendet JERSEY 2.22.2, JDK 1.8.31, MOXY AS JSON Provider.Probleme bei der Verwendung von EntityFilteringFeature und SelectableEntityFilteringFeature mit Jersey 2

Ich habe eine Ressource mit GET-Methoden zur Unterstützung von LIST/DETAIL definiert. Aufgrund der Größe meines POJO habe ich einige Filter benutzt und alles war in Ordnung.

// 1) First of all I defined the annotation. 


@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD}) 
@Retention(RetentionPolicy.RUNTIME) 
@Documented 
@EntityFiltering 
public @interface MyDetailView { 

public static class Factory extends AnnotationLiteral<MyDetailView> 
    implements MyDetailView { 

    private Factory() { 
    } 

    public static MyDetailView get() { 
     return new Factory(); 
    } 
} 


// 2) Once defined the annotation, I used to 
// programmaticaly exclude the list of subItems in the response... 


@XmlRootElement 
public class MyPojo { 

...  


    //*** THIS SHOULD BE FILTERED IF THE ANNOTATION IS NOT SPECIFIED IN THE RESPONSE *** 
    @MyDetailView 
    private List<SubItem> subItems = new ArrayList<SubItem>(); 

    public List<SubItem> getSubItems() { 
     return subItems; 
    } 

    public void setSubItems(List<SubItem> subItems) { 
     this.subItems = subItems; 
    } 

} 


// 3) I registered the EntityFilteringFeature 

    public class ApplicationConfig extends ResourceConfig { 

    public ApplicationConfig() { 

     .... 
     register(EntityFilteringFeature.class); 

    } 


// 4) Finally, I wrote the code to include/exclude the subItems 


/* 
The Resource class has getCollection() and getItem() methods... 

getCollection() adds the annotation only if filterStyle="detail" 
getItem() always add the annotation 

*/ 

@Path(....) 
@Produces(MediaType.APPLICATION_JSON) 
@Consumes(MediaType.APPLICATION_JSON) 
public class MyResource extends SecuredResource { 

    //filterStyle -> "detail" means MyDetailAnnotation 
    @GET 
    public Response getCollection(
     @QueryParam("filterStyle") String filterStyle, 
     @Context UriInfo uriInfo) { 


     //THIS CODE AFFECTS THE RESPONSE 
     boolean detailedResponse = "detail".equals(filterStyle);  
     Annotation[] responseAnnotations = detailedResponse 
      ? new Annotation[0] 
      : new Annotation[]{MyDetailView.Factory.get()}; 

     //pojo collection...   
     MyPagedCollection myCollection = new MyPagedCollection(); 

     //..... 

     ResponseBuilder builder = Response.ok(); 

     return builder.entity(myCollection, responseAnnotations).build(); 
    } 

    @GET 
    @Path("/{id}") 
    public Response getItem(@PathParam("{id}") String idS, @Context UriInfo uriInfo) { 
     MyPOJO pojo = ... 

     Annotation[] responseAnnotations = new Annotation[]{MyDetailView.Factory.get()}; 

     return Response.ok().entity(pojo, responseAnnotations).build(); 
    } 
} 

Nach dem ersten Test habe ich versucht, die SelectableEntityFilteringFeature zu verwenden, damit der Client für bestimmte Felder im Detail zu fragen, so änderte ich den ApplicationConfig

public class ApplicationConfig extends ResourceConfig { 

    public ApplicationConfig() { 

     .... 
     register(EntityFilteringFeature.class); 

     register(SelectableEntityFilteringFeature.class); 
     property(SelectableEntityFilteringFeature.QUERY_PARAM_NAME, "fields");   
    } 

und ich Fügen Sie die "fields" QueryParam zur Resource getItem() -Methode hinzu ...

Solange jedoch die SelectableEntityFilteringFeature-Klasse registriert wurde, hat die EntityFilteringFeature-Klasse nicht mehr funktioniert. Ich habe versucht, "fields" -Parameter zu einer der Resource-Methoden hinzuzufügen, es hat perfekt funktioniert. Aber die MyDetailAnnotation war völlig nutzlos.

Ich habe versucht, es zu registrieren einen DynamicFeature mit

public class MyDynamicFeature implements DynamicFeature { 

@Override 
public void configure(ResourceInfo resourceInfo, FeatureContext context) { 
    if ("MyResource".equals(resourceInfo.getResourceClass().getSimpleName()) 
       && "getItem".equals(resourceInfo.getResourceMethod().getName())) { 

      //*** IS THE CORRECT WAY TO BIND A FEATURE TO A METHOD? *** 
      // 
      context.register(SelectableEntityFilteringFeature.class); 
      context.property(SelectableEntityFilteringFeature.QUERY_PARAM_NAME, "fields"); 

    }  
} 

nun die Fragen:

1) Warum registrieren sowohl die SelectableEntityFilteringFeature Funktion des EntityFilteringFeature bricht?

2) Was ist die korrekte Methode zum Binden eines Features an eine Methode mit der DynamicFeature-Schnittstelle?

Vielen Dank im Voraus. Dies ist mein erster Beitrag zu Stack Overflow, ich hoffe, es wurde geschrieben, beschweren die Regeln.

Antwort

0

SelectableEntityFilteringFeature implictily registriert EntityFilteringFeature (Wie erwähnt here). Daher sehe ich keine Notwendigkeit, dies hinzuzufügen.

Da Sie Annotation-basierte Filter benötigen, können Sie ausschließen Registrierung SelectableEntityFilteringFeature.

Sie können nur tun,

// Set entity-filtering scope via configuration. 
.property(EntityFilteringFeature.ENTITY_FILTERING_SCOPE, new Annotation[] {MyDetailView.Factory.get()}) 
// Register the EntityFilteringFeature. 
.register(EntityFilteringFeature.class) 
// Further configuration of ResourceConfig. 

Sie können für die Nutzung und this Beispiel this Beispiel beziehen sich die Filter für die Registrierung.

So können Sie SelectableEntityFilteringFeature entfernen und versuchen Sie nur die oben genannte Möglichkeit, es zu registrieren.

+0

Danke. Aber das ist, was ich getan habe und es funktioniert (der einzige Unterschied war, dass ich die Eigenschaft in der ResourceConifg-Unterklasse nicht angegeben habe, ich habe die Annotation in der Resource-Methode hinzugefügt.Mein Ziel ist es jetzt, das SelectableEntityFilteringFeature in der Detailmethode zu verwenden (unter Verwendung der QueryParam "fields", um die Übersichtlichkeit zu verbessern, habe ich dem Code die unterschiedliche Methodensignatur hinzugefügt). In der Zwischenzeit möchte ich die getCollection() so lassen, wie sie ist (sie filtert die Antwort über MyDetailView Annotation genau wie in den von Ihnen geposteten Links erklärt). Das Problem ist, dass die unveränderte getCollection() die Filterung beendet hat. –

+0

Das Poster möchte sowohl EntityFilteringFeature als auch SelectableEntityFilteringFeature verwenden, daher ist dies keine wirkliche Antwort. Es beschreibt nur, wie nur Annotation-basierte EntityFilteringFeature verwendet wird – ChrisO