4

I am trying to implement custom controller to handle method defined in custom repository to be able to expose resources using this method via REST (according to Implementing custom methods of Spring Data repository and exposing them through REST).

Here is the configuration and other relevant code:

public class ApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

     @Override
     protected Class<?>[] getRootConfigClasses() {
        return new Class<?>[] {ApplicationConfig.class};
     }

     @Override
     protected Class<?>[] getServletConfigClasses() {
        return new Class<?>[] {RepositoryRestMvcConfiguration.class};
     }

     @Override
     protected String[] getServletMappings() {
        return new String[]{"/api/*"};
     }

}

ApplicationConfig:

@Configuration
@EnableJpaRepositories
@EnableTransactionManagement
public class ApplicationConfig {

    @Bean
    public DataSource dataSource() {
        // data source settings
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
        // em factory settings
    }

    @Bean
    public PlatformTransactionManager transactionManager() {
        // tx mng settings
    }
}

ExperimentRepository:

@RepositoryRestResource
public interface ExperimentRepository extends PagingAndSortingRepository<Experiment, Long>,
    ExperimentRepositoryCustom {

    @RestResource(rel = "byName", path = "byName")
    Page<Experiment> findByNameContaining(@Param("name") String name, Pageable pageable);

}

ExperimentRepositoryCustom:

public interface ExperimentRepositoryCustom {

    Page<Experiment> findUsingCustomFilter(...);

}

ExperimentRepositoryImpl:

public class ExperimentRepositoryImpl implements ExperimentRepositoryCustom {

    @Override
    public Page<Experiment> findUsingCustomFilter(...) {
        // search for experiment based on given filter
    }

}

ExperimentController:

@RepositoryRestController
public class ExperimentController {

    @Autowired
    private ExperimentRepository experimentRepository;


    @RequestMapping(value = "/experiments/search/findByFilter", method= RequestMethod.GET)
    @ResponseBody
    public ResponseEntity<Experiment> searchUsingFilter(@RequestParam Long id) {
        // for test purpose call method from CrudRepository (will be replaced by findUsingCustomFilter(...)) 
        return new ResponseEntity(experimentRepository.findOne(id), HttpStatus.OK);
    }
}

Project structure:

basepackage.model.Experiment
basepackage.repository.ExperimentController
basepackage.repository.ExperimentRepository
basepackage.repository.ExperimentRepositoryImpl
basepackage.repository.ExperimentRepositoryCustom
basepackage.ApplicationInitializer
basepackage.ApplicationConfig

All resources exposed by links automatically generated based on used Repositories are accessible with no problem but calling GET method on http://localhost:8080/app/api/experiments/search/findByFilter?id=1 ends with 404 (resources exposed by links automatically generated based on used Repositories work fine). I assume that ExperimentController is not registered in Spring container or I am missing some additional settings regarding controller method. Any suggestions?

Thanks in advance!

Community
  • 1
  • 1
gar_r
  • 347
  • 5
  • 13

1 Answers1

2

You need configuration to load your Controllers. One way to do this is to add a configuration class to load you Controllers and add it to your ApplicationInitializer.

//PLACE THIS IN A PACKAGE WHERE YOUR CONTROLLERS ARE
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Import;
import org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration;

@ComponentScan
@Import(RepositoryRestMvcConfiguration.class)
public class WebConfig {
}

Change you ApplicationInitializer to

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

import com.spring.data.rest.test.web.WebConfig;

public class ApplicationInitializer extends
        AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class<?>[] { ApplicationConfig.class };
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class<?>[] { WebConfig.class };
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] { "/api/*" };
    }

}
Stackee007
  • 3,196
  • 1
  • 26
  • 39