I currently have a single controller (implemented using Spring mvc), for students and teachers to upload files Controller name is FileUpoadController
I would like to break the controller functionality and extend it using:
StudentFileUploadController extends FileUpoadController
LecturerFileUpoadController extends FileUpoadController
So FileUpoadController will be abstract and maintain the base functionality.
Current controller:
#Controller
#RequestMapping(value = "/upload")
public class FileUpoadController
One solution is to make different upload mapping with two controllers
#RequestMapping(value = "/uploadStudent")
#RequestMapping(value = "/uploadLecturer")
Is it possible any other way?
It is very unlikely that those method behave exactly the same besides the different mapping. But you can use delegation instead:
public class FileUpoadController<T> {
public List<T> getList(){
// returns list of T
}
}
#Controller(value = "/uploadStudent")
public class UploadStudentController extends FileUpoadController<UploadStudent>{
#RequestMapping(method = RequestMethod.GET, value = "/list")
public #ResponseBody List<UploadStudent> getStudent() {
return super.getList();
}
}
#Controller(value = "/uploadLecturer")
public class UploadLecturerController extends FileUpoadController<UploadLecture>{
#RequestMapping(method = RequestMethod.GET, value = "/list")
public #ResponseBody List<UploadLecture> getLecture() {
return super.getList();
}
}
for more details please refer this:
https://www.codeproject.com/Articles/799677/The-Hierarchy-of-Controller-Class-in-ASP-NET-MVC
Related
Using OpenApi to generate interfaces with "async : 'true'" to have asynchronous controller method handling, I tried to implement those interfaces but I get always 404. I checked also the '/actuator/mappings' method to see whether my endpoints but they don't appear in that list of mappings.
I tried also to have async method without inheriting from an interface and the mapping was correctly considered.Below are some examples:
Async from interface
public interface TestApi {
#GetMapping(value = "/greeting-asnyc-api/{name}", produces = {"application/json", "application/xml"})
CompletableFuture<ResponseEntity<String>> greetingAsync(#PathVariable("name") final String name);
}
// This example doesn't work and returns 404
#RestController
public class TestApiController implements TestApi {
#Async
#Override
public CompletableFuture<ResponseEntity<String>> greetingAsync(final String name) {
return CompletableFuture.completedFuture(ResponseEntity.ok("Greeting " + name));
}
}
// This example works fine
#RestController
public class TestController {
#Async
#GetMapping(value = "/greeting/{name}", produces = {"application/json"})
public CompletableFuture<ResponseEntity<String>> greeting(#PathVariable("name") final String name) {
return CompletableFuture.completedFuture(ResponseEntity.ok("Greeting " + name));
}
}
The first example, i.e., TestApiController, doesn't work unfortunately and returns always 404 (also not found on '/actuator/mappings'), unlike the second example which works fine without any issues (can also be found on '/actuator/mappings')
Sync from interface
public interface TestApi {
#GetMapping(value = "/greeting-sync/{name}", produces = {"application/json", "application/xml"})
ResponseEntity<String> greeting(#PathVariable("name") final String name);
}
#RestController
public class TestApiController implements TestApi {
#Override
public ResponseEntity<String> greeting(final String name) {
return ResponseEntity.ok("Greeting " + name);
}
}
The example above also works fine when inheriting synchronous method from interface.
Did anyone face similar issue? Thanks for helping
There are 2 controllers having same #RequestMapping value :
package com.ambre.hib.controller;
#Controller
public class AppointmentsController {
#RequestMapping(value = "/new", method = RequestMethod.GET)
public AppointmentForm getNewForm() {
return new AppointmentForm();
}
}
package com.ambre.hib.controller;
#Controller
public class ClientsController {
#RequestMapping(value = "/new", method = RequestMethod.GET)
public ClientForm getNewForm() {
return new ClientForm();
}
}
So the 2 controllers have same "/new" action.
Now from a jsp page I want to target a link to the "/new" action of the second controller : <img src="resources/images/plus.png" />
This writing is ambiguous because Spring does not know into which controller to look ! So how to specify the controller name in the link target ?
It's not possible to have two or more controller methods with the same #RequestMapping. The dispatcher won't know wich method to call.
You could set a base request mapping for each controller:
package com.ambre.hib.controller;
#Controller
#RequestMapping("/appointments")
public class AppointmentsController {
#RequestMapping(value = "/new", method = RequestMethod.GET)
public AppointmentForm getNewForm() {
return new AppointmentForm();
}
}
package com.ambre.hib.controller;
#Controller
#RequestMapping("/clients")
public class ClientsController {
#RequestMapping(value = "/new", method = RequestMethod.GET)
public ClientForm getNewForm() {
return new ClientForm();
}
}
If so, the way of calling each would be <a href="<c:url value='/appointments/new' />"> for the first controller and
<a href="<c:url value='/clients/new' />"> for the second
You need to narrow down the request using the "params" option. For example
#Controller
public class HelloWorldController {
#RequestMapping(value="/fetch", params = {"id=100"})
public String getInfo1(#RequestParam("id") String id) {
System.out.println("Inside getInfo1");
return "success";
}
#RequestMapping(value="/fetch", params = {"id=200"})
public String getInfo2(#RequestParam("id") String id) {
System.out.println("Inside getInfo2");
return "success";
}
}
When you access the URL /fetch?id=100 , method getInfo1() is called. When you access URL /fetch?id=200 , method getInfo2() is called and when you access /fetch?id=300 , HTTP Status 404 is received. In this case the "id" parameter is just another parameter which you use to narrow down the request to your preferred method in the controller.
I am using Spring-Boot 1.2.7 for developing Spring-Hateoas application with Spring-Data-JPA.
I have developed controller class with methods which returns Resource.
I want to create Exception with HttpStatus and use it in controller class for GET, POST, PUT and DELETE. Please assist me, I am new to this.
Controller Class - ArticleController
#RestController
#RequestMapping(value = "/api/articles")
public class ArticleController {
#Autowired
private ArticleService articleService;
#Autowired
private ArticleRepository articleRepository;
#Autowired
private ArticleResourceAssembler articleResourceAssembler;
/*#RequestMapping(method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public Collection<Resource<Article>> getArticles() {
Collection<Article> articles = articleService.findAll();
List<Resource<Article>> resources = new ArrayList<Resource<Article>>();
for (Article article : articles) {
resources.add(getArticleResource(article));
}
return resources;
}*/
#RequestMapping(method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public PagedResources<Article> getArticles(Pageable pageable, PagedResourcesAssembler assembler) {
Page<Article> articles = articleService.findAll(pageable);
return assembler.toResource(articles, articleResourceAssembler);
}
#RequestMapping(value = "/{article_id}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public Resource<Article> getArticle(#PathVariable(value = "article_id") long article_id) {
Article article = articleService.findOne(article_id);
if (article == null) {
ResponseEntity.status(HttpStatus.NOT_FOUND);
}
return getArticleResource(article);
}
// Insert Article
#RequestMapping(method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Article> createArtilce(#RequestBody Article article) {
article.setCreated(new Date());
Article savedArticle = articleService.create(article);
article.add(linkTo(methodOn(ArticleController.class).getArticle(savedArticle.getArticle_id()))
.withSelfRel());
// I want to return here HttpStatus.NOT_FOUND
}
private Resource<Article> getArticleResource(Article article) {
Resource<Article> resource = new Resource<Article>(article);
// Link to Article
resource.add(linkTo(methodOn(ArticleController.class).getArticle(article.getArticle_id())).withSelfRel());
return resource;
}
}
You need to implement a class for the exception (that is extends from RuntimeException) and annotated with #ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) or another Status code, and where you want throw that status, you need throw your CustomException.
For Exceptions you didn't write, can use a exception handler method inside your controller like this:
#ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
#ExceptionHandler({ExternalException.class})
public void metodoCuandoExcepcionEsLanzada(){
//logging and processing
}
I would like to write whole controller to work with entity.
I would like to declare the id of entity on class level and use it on each method. Here is the controller class:
#Controller
#RequestMapping(value="/job/{j_id}/instance")
public class JobController extends GenericController {
private final String htmlDir = "job/";
#RequestMapping(value="{i_id}/open", method=RequestMethod.GET)
public ModelAndView open(#PathVariable Long instance_id) {
ModelAndView result = new ModelAndView(htmlDir + "instance");
result.addObject("instance_id", instance_id);
Here I would like to use variable j_id from #RequestMapping
return result;
}
}
Can I achive this? Please help. Give me some code snippest please.
Have a try like this
#Controller
#RequestMapping(value="/job/{j_id}/instance")
public class JobController {
private final String htmlDir = "job/";
#RequestMapping(value="{i_id}/open", method=RequestMethod.GET)
public ModelAndView open(#PathVariable(value="j_id") Long instance_id) {
ModelAndView result = new ModelAndView(htmlDir + "instance");
result.addObject("instance_id", instance_id);
System.out.println("Instance Id -------------> " + instance_id);
return result;
}
}
Please notic "#PathVariable(value="j_id")"
To get both variables, you can change that line as following:
#RequestMapping(value="{i_id}/open", method=RequestMethod.GET)
public ModelAndView open(#PathVariable(value="j_id") Long jnstance_id, #PathVariable(value="i_id") Long instance_id) {
.....
}
i try make a generic controller with some methods, so i don´t need re-writer common codes, but don´t work, why???
#Controller("/home/teste")
public class CtrlTeste extends ControladorGenericoSpring<Assistenciado>
{
public String path;
public CtrlTeste()
{
super(Assistenciado.class);
path = "/home/teste";
setPacoteServico("servico.assistenciado");
setPrefixo("Serv");
setNomeEntidade("Assistênciado");
}
#RequestMapping
public String teste(#RequestParam(value = "id", required= true)Long id, Model model)
{
Assistenciado ass = getServico().buscarPorId(id);
model.addAttribute("assistenciado", ass);
return "/home";
}
}
You're currently specifying the name of the bean. Try with:
#Controller
#RequestMapping("/home/teste")
public class CtrlTeste extends ControladorGenericoSpring<Assistenciado> {
...
}