简体   繁体   中英

Using Spring Data Rest RepositoryEntityLinks outside of Controller

I would like to use the RepositoryEntityLinks class to get the link to a resource at various places in my code as per section 12.1 of the current Spring Data Rest manual

12.1. Programmatic Links Sometimes you need to add links to exported resources in your own custom built Spring MVC controller s. There are three basic levels of linking available:

...

3 Using Spring Data REST's implementation of RepositoryEntityLinks.

http://docs.spring.io/spring-data/rest/docs/current/reference/html/#_programmatic_links

I note the docs refer explicitly to "...your own custom built Spring MVC controllers" and it would seem that is the only place it is available. I would like to use the configured instance in a Spring Security AuthenticationSuccessHandler however the application fails to start with the error:

No qualifying bean of type[org.springframework.data.rest.webmvc.support.RepositoryEntityLinks] found

I have been able to successfully inject it to a controller as expected.

Can I use the RepositoryEntityLinks class outside of a Spring MVC Controller?

public class RestAuthenticationSuccessHandler implements AuthenticationSuccessHandler
{
  @Autowired
  private RepositoryEntityLinks entityLinks;

  @Override
  public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
      Authentication authentication) throws IOException, ServletException
  {
    //do something with entityLinks
  }
}

Yes, You can. I have successfully used it in Assembler which generates links from HATEOAS model. Altough there may be some restrictions on where RepositoryEntityLinks class can be injected, for sure it can be used outside of Controllers.

Below you can see my working example. If anyone wnders this class extends ResourceAssemblerSupport which is part of spring-hateoas module. Maybe that's the thing that enables injection here.

@Component
public class UserAssembler extends ResourceAssemblerSupport<UserEntity, UserResource> {

    @Autowired
    private RepositoryEntityLinks repositoryEntityLinks;

    public UserAssembler() {
        super(UserController.class, UserResource.class);
    }

    @Override
    public UserResource toResource(UserEntity userEntity) {
        Link userLink = repositoryEntityLinks.linkToSingleResource(UserEntity.class, userEntity.getId());
        Link self = new Link(entryLink.getHref(), Link.REL_SELF);
        return new UserResource(userEntity, self);
    }
}

The following works for me:

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class RestApiIntegrationTests {

    @Autowired
    private RepositoryEntityLinks repositoryEntityLinks;

    @BeforeEach
    public void initServletRequestAttributes() {
        MockHttpServletRequest request = new MockHttpServletRequest();
        ServletRequestAttributes requestAttributes = new ServletRequestAttributes(request);
        RequestContextHolder.setRequestAttributes(requestAttributes);
    }

    @Test
    void test() { 
        System.out.println(repositoryEntityLinks.linkToCollectionResource(SomeClass.class));
    }

}

The code is based on spring-data-rest-tests-core : AbstractControllerIntegrationTests , TestMvcClient .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM