rest controller for Spring Data REST repository - spring

I have implemented a simple Spring Data REST repository which works as expected and I am fine with it exposing all methods. This is what it looks like:
#RepositoryRestResource(path = "employees")
public interface EmployeeRepository extends PagingAndSortingRepository<Employees, Integer>
{ }
Now I would like to wrap this repository in a controller, so I can later add Hystrix to it for fallbacks and exception handling. My issue is now, that I would like to keep the behavior of the repository above and just pass the response through the controller to the client. Is there a possible way without reimplementing all the methods of my repository (including sorting and pagination)?
This is what my controller currently looks like:
#RepositoryRestController
public class EmployeeController {
private final EmployeeRepository repository;
#Autowired
public EmployeeController(EmployeeRepository repo) {
repository = repo;
}
// Here I would like to return the same respone as my repository does
#RequestMapping(method = GET, value = "/employees")
public #ResponseBody ResponseEntity<?> parseRequest() {
return ResponseEntity.ok("hi");
}
}

It seems that you could simply call the method from your repository. Did you try it?
#RepositoryRestController
public class EmployeeController {
private final EmployeeRepository repository;
#Autowired
public EmployeeController(EmployeeRepository repository) {
this.repository = repository;
}
#RequestMapping(method = GET, value = "/employees")
public #ResponseBody ResponseEntity<List<Employee>> parseRequest() {
List<Employee> employees = repository.getEmployees();
return new ResponseEntity(employees, HttpStatus.OK);
}
}

Related

How to access a collection of SseEmitters located inside a #Service Class

The sses Map has been moved from MessageController class to a class annotated with #Service MessageTemplate.class . Now we need a way to add SseEmitter instances (created inside openConn()) to the sses map inside MessageTemplate class.
Map may not be the best choice here, if so, what other cache alternatives available because I need a away to send messages back to individual clients?
#Controller
#RequestMapping(value="/")
public class MessageController{
#Autowired MessageOperations mesgOps;
//Moved to MessageTemplate
Map<String, SseEmitter> sses = new ConcurrentHashMap<>();
#GetMapping(value = "/conn/{username}")
public SseEmitter openConn(#PathVariable("username") String username){
SseEmitter sseEmitter = new SseEmitter(3600000L);
sses.put(username, sseEmitter);
return sseEmitter;
}
#Service
public class MessageTemplate implements MessageOperations{
//The above map now resides here.
Map<String, SseEmitter> sses = new ConcurrentHashMap<>();
..
}
Assuming, all the presented abstraction in the question are “custom” (the code that was written in your organization) and do not belong to spring ecosystem by themselves, I see the following:
A MessageTemplate is a singleton-scoped bean driven by spring
The controller is also a singleton bean.
MessageOperations interface is your custom interface that you’re using for injection.
In this case the obvious change would be:
interface MessageOperations {
SseEmitter associateSseEmitterWithUser(String userName);
}
#Service
public class MessageTemplate implements MessageOperations {
private Map<String, SseEmitter> sses = new ConcurrentHashMap<>();
// other existing code you might already have
public SseEmitter associateSseEmitterWithUser(String username) {
SseEmitter sseEmitter = new SseEmitter(3600000L);
sses.put(username, sseEmitter);
return sseEmitter;
}
}
#Controller
#RequestMapping(value = “/“)
public class MessageController {
#Autowired MessageOperations mesgOps;
#GetMapping(value=“/conn/{username})
public SseEmitter openConn(#PathVariable(“username”) String username) {
return mesgOps.associateSseEmitterWithUser(username);
}
}

Spring Boot Application ,JPA,

I have created a small application using the spring boot framework. I have created a Rest Controler class.
and deploy it on tomcat, but I am getting 404 error i.e
The origin server did not find a current representation for the target resource or is not willing to disclose that one exists.
#RestController
#RequestMapping("students")
public class StudentController {
#Autowired
StudentRepository repository;
#GetMapping
public List<Student> getAllStudents() {
return (List<Student>) repository.findAll();
}
#PostMapping
public String createStudent() {
return "created";
}
#PutMapping
public String updateStudent() {
return "updated";
}
#DeleteMapping
public String deleteStudent() {
return "deleted";
}
}
You are missing slash in annotation, it should look like this
#RestController
#RequestMapping("/students")
public class StudentController {
...
}

#RepositoryRestController not recognized

I have the following controller:
#RepositoryRestController
public class TestController {
#RequestMapping(value = "/testables", method = RequestMethod.GET)
public String get(){
return "testin it";
}
}
And it is not picked up by Spring. I get 404 when I hit /apiroot/testables address. If I change it to be #RestController and add the api root to request mapping value, then it works. Also, if I change the mapping to point to "/orders/testables", it works as #RepositoryRestController. I also have the following controller in the same package which works fine:
#RepositoryRestController
public class SendEmailController {
#Autowired
private MessageSource messageSource;
#Autowired
private JavaMailSender javaMailSender;
#Autowired
private OrderRepository orderRepository;
#RequestMapping(value = "/orders/{id}/sendOrderEmailToSupplier")
public void sendOrderEmailToSupplier(#PathVariable("id") Long id, WebRequest request) throws MessagingException {...
#RepositoryRestController deal with basePath only for resources which it manage. In other cases the path should not contain the "base".
If you want to build custom operations underneath basePath, you can use #BasePathAwareController.

Spring Data MongoDB custom repository method implementation

I followed the instructions outlined here to implement custom methods for my MongoDB Repository. However, none of the custom methods appear to be usable (findAllSeries and uploadSomeSeries do not seem to be found by spring). I have checked the naming
SeriesRepository:
#RepositoryRestResource(collectionResourceRel = "series", path = "series", excerptProjection = SeriesProjection.class)
public interface SeriesRepository extends MongoRepository<Series, String>, SeriesRepositoryCustom {
List<Series> findByWinnerId(#Param("id") String id);
}
SeriesRepositoryCustom:
public interface SeriesRepositoryCustom {
ResponseEntity<Void> createSeries(Series series);
}
SeriesRepositoryImpl:
public class SeriesRepositoryImpl implements SeriesRepositoryCustom {
private final MongoOperations operations;
#Autowired
public SeriesRepositoryImpl(MongoOperations operations) {
this.operations = operations;
}
#Override
#RequestMapping(method = RequestMethod.POST)
public ResponseEntity<Void> createSeries(#RequestBody Series series) {
// ... implementation
}
}
Got it working; via this answer, I had to implement a controller for my repository, and delegate the call to the method defined in the custom repository:
#RepositoryRestController
public class SeriesController {
private final SeriesRepository repository;
#Autowired
public SeriesController(SeriesRepository repo) {
repository = repo;
}
#RequestMapping(value = "/series", method = RequestMethod.POST)
public ResponseEntity<Void> create(#RequestBody Series series) {
return repository.createSeries(series);
}
}

Spring Data Rest : How to expose custom rest controller method in the HAL Browser

i have created a custom rest controller and I can access the API and get the result from the resource, the problem is, it doesn't appear in the HAL Browser.. how to expose this custom method in the HAL Browser? Thank You...
#RepositoryRestController
public class RevisionController {
protected static final Logger LOG = LoggerFactory
.getLogger(RevisionController.class);
private final DisciplineRepository repository;
Function<Revision<Integer, Discipline>, Discipline> functionDiscipline = new Function<Revision<Integer, Discipline>, Discipline>() {
#Override
public Discipline apply(Revision<Integer, Discipline> input) {
return (Discipline) input.getEntity();
}
};
#Inject
public RevisionController(DisciplineRepository repository) {
this.repository = repository;
}
#RequestMapping(method = RequestMethod.GET, value = "/disciplines/search/{id}/revisions")
public #ResponseBody ResponseEntity<?> getRevisions(
#PathVariable("id") Integer id) {
Revisions<Integer, Discipline> revisions = repository.findRevisions(id);
List<Discipline> disciplines = Lists.transform(revisions.getContent(),
functionDiscipline);
Resources<Discipline> resources = new Resources<Discipline>(disciplines);
resources.add(linkTo(
methodOn(RevisionController.class).getRevisions(id))
.withSelfRel());
return ResponseEntity.ok(resources);
}
}
Register a bean that implements a ResourceProcessor<RepositoryLinksResource> and you can add links to your custom controller to the root resource, and the HAL Browser will see it.
public class RootResourceProcessor implements ResourceProcessor<RepositoryLinksResource> {
#Override
public RepositoryLinksResource process(RepositoryLinksResource resource) {
resource.add(ControllerLinkBuilder.linkTo(ControllerLinkBuilder.methodOn(RevisionController.class).getRevisions(null)).withRel("revisions"));
return resource;
}
}

Resources