Pregunta

I am using spring-data-rest(1.0.0.RELEASE) in my spring-mvc application But I am getting following problem

In my WebConfig

@Import(RepositoryRestMvcConfiguration.class)
public static class WebConfiguration extends WebMvcConfigurationSupport{...}

Here this case RepositoryRestMvcConfiguration has a bean RepositoryRestController which has method listRepositories(...) annotated with

@RequestMapping(value = "/", method = RequestMethod.GET)

Now the problem is that when I am hitting at the root context ("/") then I am getting links to my repositories, like below

{
  "links" : [ {
    "rel" : "content",
    "href" : "http://localhost:7070/appName/content"
  }, {
    "rel" : "language",
    "href" : "http://localhost:7070/appName/language"
  } ],
  "content" : [ ]

}

But I want to show index.html file instead.

I want to disable discovery of links at root context.

Event I tried with my custom controller to map to the root context("/") but spring at the first priority matches the RepositoryRestController's.listRepositories(...) method.

Its not coming to my controller method. In log its comes like this

**RepositoryRestHandlerMapping**: 185 - Mapped "{[/],methods=[GET],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public org.springframework.http.ResponseEntity<?> org.springframework.data.rest.webmvc.RepositoryRestController.listRepositories(org.springframework.http.server.ServletServerHttpRequest,java.net.URI) throws java.io.IOException
**RequestMappingHandlerMapping**: 185 - Mapped "{[/],methods=[GET],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public java.lang.String xxx.xx.xx.AccessController.getIndex()
¿Fue útil?

Solución 2

Here is how I achieved this

  1. sub classed RepositoryRestMvcConfiguration, then throwing some custom exception

  2. catching the exception in Advised Controller and there returning "index.html"

  3. use sub classed class to import in configuration

Step 1

@Configuration
public class CustomRepositoryRestMvcConfiguration extends RepositoryRestMvcConfiguration {
    @Override
    public RepositoryRestController repositoryRestController() throws Exception {
        RepositoryRestController restController = new RepositoryRestController(){
            @Override
            public ResponseEntity<?> listRepositories(ServletServerHttpRequest request, URI baseUri) throws IOException {
                throw new RootContextRepositoryException();                
            }
        };

        return restController;
    }
}

Step 2

@ControllerAdvice
public class BaseAdvisedController {

    @ExceptionHandler({RootContextRepositoryException.class})
    public String rootContextRepositoryExceptionHandler(RootContextRepositoryException ex){
        return "index.html";
    }

}

Step 3

@Import(CustomRepositoryRestMvcConfiguration.class)
public static class WebConfiguration extends WebMvcConfigurationSupport{...}

This solved my problem

Otros consejos

I've faced the same issue, and solved it like following :

1) Switched to spring-data-rest-webmvc 1.1.0.M1

2) Split your context configuration to web-config and rest-config

WebConfig.java

@Configuration
@EnableHypermediaSupport
@EnableSpringDataWebSupport
@EnableWebMvc
@ComponentScan(basePackages = {"com.yourcompanyname.XXX"})
public class WebConfig extends WebMvcConfigurationSupport {

@Bean
public InternalResourceViewResolver viewResolver() {
    InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
    viewResolver.setViewClass( JstlView.class );
    viewResolver.setPrefix( "/WEB-INF/views/" );
    viewResolver.setSuffix( ".jsp" );
    return viewResolver;
}

@Bean
public ReloadableResourceBundleMessageSource messageSource()
{
    ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
    messageSource.setBasename( "/resources/messages" );
    messageSource.setCacheSeconds( 0 );
    return messageSource;
}

@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
    configurer.defaultContentType(MediaType.APPLICATION_JSON);
}


@Override
@Bean
public RequestMappingHandlerMapping requestMappingHandlerMapping() {

    RequestMappingHandlerMapping handlerMapping = new RequestMappingHandlerMapping() {

        @Override
        protected boolean isHandler(Class<?> beanType) {
            return beanType == null || ClassUtils.getPackageName(beanType).startsWith("org.springframework.data") ? false
                    : super.isHandler(beanType);
        }
    };

    handlerMapping.setOrder(0);
    handlerMapping.setInterceptors(getInterceptors());
    handlerMapping.setContentNegotiationManager(mvcContentNegotiationManager());

    return handlerMapping;
}

@Override
@Bean
public HandlerMapping resourceHandlerMapping() {
    AbstractHandlerMapping handlerMapping = (AbstractHandlerMapping) super.resourceHandlerMapping();
    handlerMapping.setOrder(-1);
    return handlerMapping;
}

@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/resources/**").addResourceLocations("/resources/").setCachePeriod(31556926);
}

RESTConfig.java

@Configuration
public class RESTConfig extends RepositoryRestMvcConfiguration {
}

Then create webapp initializer classes which replaces registration in web.xml (servlet-api 3.0+ required). In following example spring-data-rest path is set to /rest/, also included JPA configuration class for my own proposes. We will register 2 servlets in 2 separate classes, one for main "/" and one for "/rest/" path :

WebAppInitializer.java

public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

/*
* (non-Javadoc)
* @see org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer#getRootConfigClasses()
*/
@Override
protected Class<?>[] getRootConfigClasses() {
    return new Class<?>[] { JpaConfig.class };
}

/*
 * (non-Javadoc)
 * @see org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer#getServletConfigClasses()
 */
@Override
protected Class<?>[] getServletConfigClasses() {
    return new Class<?>[] { WebConfig.class };
}

/*
 * (non-Javadoc)
 * @see org.springframework.web.servlet.support.AbstractDispatcherServletInitializer#getServletMappings()
 */
@Override
protected String[] getServletMappings() {
    return new String[] { "/" };
}



/*
 * (non-Javadoc)
 * @see org.springframework.web.servlet.support.AbstractDispatcherServletInitializer#getServletFilters()
 */
@Override
protected javax.servlet.Filter[] getServletFilters() {
    return new javax.servlet.Filter[] { new OpenEntityManagerInViewFilter() };
}

}

RestAppConfig.java

public class RestAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

/*
* (non-Javadoc)
* @see org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer#getRootConfigClasses()
*/
@Override
protected Class<?>[] getRootConfigClasses() {
    return new Class<?>[] { JpaConfig.class };
}

/*
 * (non-Javadoc)
 * @see org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer#getServletConfigClasses()
 */
@Override
protected Class<?>[] getServletConfigClasses() {
    return new Class<?>[] { RESTConfig.class };
}

/*
 * (non-Javadoc)
 * @see org.springframework.web.servlet.support.AbstractDispatcherServletInitializer#getServletMappings()
 */
@Override
protected String[] getServletMappings() {
    return new String[] { "/rest/*" };
}



/*
 * (non-Javadoc)
 * @see org.springframework.web.servlet.support.AbstractDispatcherServletInitializer#getServletFilters()
 */
@Override
protected javax.servlet.Filter[] getServletFilters() {
    return new javax.servlet.Filter[] { new OpenEntityManagerInViewFilter() };
}

}

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top