2015-11-06 11 views
5

Sto tentando di aggiungere qualche business logic aggiuntivo agli endpoint generati automaticamente da RepositoryRestResource. Si prega di consultare il codice qui sotto:Spring Data Rest/Spring Hateoas Custom Controller - PersistentEntityResourceAssembler

risorse:

@RepositoryRestResource(collectionResourceRel="event", path="event") 
public interface EventRepository extends PagingAndSortingRepository<Event, Long> { 

} 

Controller:

@RepositoryRestController 
@RequestMapping(value = "/event") 
public class EventController { 

    @Autowired 
    private EventRepository eventRepository; 

    @Autowired 
    private PagedResourcesAssembler<Event> pagedResourcesAssembler; 

    @RequestMapping(method = RequestMethod.GET, value = "") 
    @ResponseBody 
    public PagedResources<PersistentEntityResource> getEvents(Pageable pageable, 
     PersistentEntityResourceAssembler persistentEntityResourceAssembler) { 

    Page<Event> events = eventRepository.findAll(pageable); 

    return pagedResourcesAssembler.toResource(events, persistentEntityResourceAssembler); 
    } 
} 

Ho guardato i seguenti due articoli StackOverflow:

Mi sento come se fossi vicino, ma il problema che sto affrontando è che:

return pagedResourcesAssembler.toResource(events, persistentEntityResourceAssembler); 

restituisce un errore che dice:

"The method toResource(Page<Event>, Link) in the type PagedResourcesAssembler<Event> is not applicable 
for the arguments (Page<Event>, PersistentEntityResourceAssembler)". 

Il metodo toResource ha una firma del metodo che accetta un ResourceAssembler, ma non sono sicuro di come implementarlo correttamente e non riesco a trovare alcuna documentazione in merito.

Grazie in anticipo, - Brian

Modifica

Il mio problema è che ho pensato che avrei potuto ignorare i metodi del controller che sono create automaticamente da @RepositoryRestResource annotazioni senza dover creare la mia risorsa e assemblatore di risorse. Dopo aver creato l'assemblatore di risorse e risorse sono stato in grado di aggiungere la mia logica aziendale all'endpoint.

risorse:

public class EventResource extends ResourceSupport { 
    private String name; 

    public String getName() { 
    return name; 
    } 

    public void setName(String name) { 
    this.name = name; 
    } 
} 

Resource Assembler:

@Component 
public class EventResourceAssembler extends ResourceAssemblerSupport<Event, EventResource> { 

    public EventResourceAssembler() { 
    super(EventController.class, EventResource.class); 
    } 

    @Override 
    public EventResource toResource(Event entity) { 
    EventResource eventResource = createResourceWithId(entity.getId(), entity); 
    eventResource.setName(entity.getName()); 
    return eventResource; 
    } 
} 

controller Aggiornato:

@RepositoryRestController 
@RequestMapping(value = "/event") 
public class EventController { 

    @Autowired 
    private EventRepository eventRepository; 

    @Autowired 
    private EventResourceAssembler eventResourceAssembler; 

    @Autowired 
    private PagedResourcesAssembler<Event> pageAssembler; 

    @RequestMapping(method = RequestMethod.GET, value = "") 
    @ResponseBody 
    public PagedResources<EventResource> getEvents(Pageable pageable) { 
    Page<Event> events = eventRepository.findAll(pageable); 

    // business logic 

    return pageAssembler.toResource(events, eventResourceAssembler); 
    } 
} 

La cosa che non mi piace di questo è che sembra annullare l'obiettivo di avere una RepositoryRestResource. L'altro approccio sarebbe utilizzare i gestori di eventi che verrebbero richiamati prima e/o dopo le operazioni di creazione, salvataggio e cancellazione.

@RepositoryEventHandler(Event.class) 
public class EventRepositoryEventHandler { 

    @HandleBeforeCreate 
    private void handleEventCreate(Event event) { 
    System.out.println("1"); 
    } 
} 

Non sembrano esserci eventi per le operazioni findAll o findOne. Ad ogni modo, entrambi questi approcci sembrano risolvere il mio problema di estendere i metodi del controller generato automaticamente da RepositoryRestResource.

+1

http://stackoverflow.com/questions/21346387/how-to-correctly-use-pagedresourcesassembler-from-spring-data potrebbe fornire ulteriori informazioni. – Jason

+0

@Jason Grazie a questo link sicuramente mi ha aiutato nella giusta direzione. – bmclachlin

risposta

1

Richiede un PagedResourcesAssembler, Spring ne inietterà uno per te se lo chiedi.

public PagedResources<Foo> get(Pageable page, PagedResourcesAssembler<Foo> assembler) { 
    // ... 
} 

In questo caso la risorsa è Foo.Sembra che nel tuo caso la risorsa che stai cercando di restituire sia una Event. Se è così, mi aspetto il vostro codice a guardare qualcosa di simile:

private ResourceAssembler<Event> eventAssembler = ...; 
public PagedResources<Event> get(Pageable page, PagedResourcesAssembler<Event> pageAssembler) { 
    Event event = ...; 
    return eventAssembler.toResource(event, pageAssembler); 
} 

si fornisce il ResourceAssembler<Event> che racconta primavera come trasformare Event in un Resource. Spring inietta lo PagedResourcesAssembler<Event> nel metodo del controller per gestire i collegamenti di impaginazione. Combinali chiamando toResource e passando per l'iniettato pageAssembler.

Il risultato finale può essere restituito semplicemente come un corpo come sopra. Potresti anche utilizzare cose come HttpEntity per ottenere un maggiore controllo sui codici di stato e sulle intestazioni.

Nota: lo ResourceAssembler fornito può essere letteralmente qualcosa di semplice come avvolgere la risorsa, ad esempio Event, con un oggetto Resource. Generalmente ti consigliamo di aggiungere qualsiasi link pertinente.

+0

Grazie per la risposta. Ho pensato che forse era possibile sovrascrivere gli endpoint generati automaticamente dall'annotazione RepositoryRestResource senza dover creare un EventResource e un EventResourceAssembler. La soluzione migliore potrebbe essere quella di utilizzare una classe con l'annotazione RepositoryEventHandler e utilizzare gli eventi emessi dall'esportatore REST. In questo modo non devo toccare il mio EventRepository e posso aggiungere la mia logica di business a questi endpoint. – bmclachlin