How can I dynamically create an URL for a Controller action?
Consider the following case:
#Controller
#RequestMapping("controller")
public class Controller {
#RequestMapping("url")
public String method() {
return "Whatever"
}
}
What I'd like to do is get the base URL and concat controller/url to it.
For this behavior, Laravel for example provides the URL helper (action() method). Is there something similar in Spring Boot?
you can use UriComponentsBuilder to get the current url and concat the additional part to it
#Controller
#RequestMapping("controller")
public class Controller {
#RequestMapping("url")
public String method(UriComponentBuilder ucb) {
URI uri = ucb.path("/url").build().toUri();
return "Whatever"
}
}
There is a library present for spring boot framework. Which you need to add in your project in order to generate link dynamically. The gradle dependency of this library is given below.
compile 'org.springframework.boot:spring-boot-starter-hateoas:2.1.4.RELEASE'
I am assuming your build system is gradle but if you are using maven then please use below syntax.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-hateoas</artifactId>
<version>2.1.4.RELEASE</version>
</dependency>
After than you can generate link dynamically as below.
WebMvcLinkBuilder.linkTo(Controller.class).slash("url").withSelfRel().getHref();
I think using #PathVariable will help you
#Controller
#RequestMapping(value="/controller")
public class Controller {
#RequestMapping(value="/url/{id}", method=RequestMethod.GET)
public String method(#PathVariable("id") String id) {
System.out.println("the url value : "+id );
return "Whatever"
}
}
then you can call the method using /controller/url/{here the value}
example /controller/url/www.google.com
if you want to map only Controller , using a property file
application.properties
server.context-path=/rest
If your Controllers are serving Data from a Repository, then Spring Data REST can take out much of the boilerplate & solve your initial problem.
Spring Data REST
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
You can control the base URL by using a property file.
application.properties
spring.data.rest.basePath=/rest
That's you want /rest concat controller/url
Related
My OpenApi gone crazy... i created 2 simple rest APIs
#RequestMapping("/inWithHibernate")
#PutMapping
public void inDbMobile() {
hibernateInsert.inDB();
}
#RequestMapping("/outWithHibernate")
#GetMapping
public MobileEntity outDbMobile(#RequestParam(name = "id")Long id) {
return hibernateInsert.fromDB(id);
}
as i understand it it should show one Put method and one Get method...Instead of that is shows all of the methods, can you please explain what is happening ?
my dependency
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>1.6.12</version>
</dependency>
The #RequestMapping tells Spring that any HTTP request with the specified path should be mapped to the corresponding method. The path should be specified as an argument of the #PutMapping and #GetMapping annotations and the #RequestMapping annotation should be removed.
I am implementing a rest-full Web service with Jersey which accepts http request from client in json form.
On fortify scan I am getting critical issue :-"mass assignment insecure binder configuration".
I want to bind the json values in htttp request to the model class in my server side code and since it is a small module I want to avoid using Spring MVC framework.
Below is my code snippet which is working fine but I need to map json request to model class below without using Spring MVC.
#POST
#Path("/TimRestService")
#Consumes({MediaType.APPLICATION_JSON})
#Produces({MediaType.APPLICATION_JSON})
public Response crunchifyREST**(JsonObject model**, #Context HttpServletRequest request) {
System.out.println(model);
return Response.status(200).entity(model).build();
}
This is the model class :-
public class ActivateService {
public String mWalletToken;
public String topMerchantEMPID;
public String serviceCategory;
}
I checked these links , however the answer is more specific to Spring MVC fmwrk:
What is the solution for Mass Assignment: Insecure Binder Configuration Vulnerability?
How to fix Mass Assignment: Insecure Binder Configuration (API Abuse, Structural) in java
This can be implemeted via Jacksonson . Jackson is one of the best JSON Providers/parsers and can be used with Jersey in Rest implemetation.The REST services will produce and consume JSON and the JSON serialization and de-serialization happens automatically behind the scenes
Create View class as :
public class View {
public static class Editable {}
public static class Viewable extends Editable {}
public static class Internal extends Viewable {}
}
Create Model class as :
#JsonIgnoreProperties(ignoreUnknown = true)
#XmlRootElement(name = "activateService")
public class ActivateService implements Serializable {
#JsonView(View.Editable.class)
public String mWalletToken;
#JsonView(View.Editable.class)
public String topMerchantEMPID;
#JsonView(View.Editable.class)
public String serviceCategory;
}
and the Rest -full web service method :
#POST
#Path("/TimRestService")
#Consumes({MediaType.APPLICATION_JSON})
#Produces({MediaType.APPLICATION_JSON})
public Response crunchifyREST(#JsonView(View.Editable.class) final ActivateService model, #Context HttpServletRequest request) {
In JAX-RS, if one model(either request or response) is annotated with #JsonView(View.Editable.class), in our case add method, Jackson will only serialize or deserialize fields that are annotated with #JsonView(View.Editable.class).
In our case, client can only pass editableField, if client pass any other fields, server will just silently ignore them.
Use below dependencies in pom.xml
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-
databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.5</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.sun.jersey/jersey-json -->
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-json</artifactId>
<version>1.19.4</version>
</dependency>
Source :- https://www.owasp.org/index.php/Mass_Assignment_Cheat_Sheet
and http://lifelongprogrammer.blogspot.com/2015/09/using-jackson-view-to-protect-mass-assignment.html
it also works just by placing this in the pojo or model class
#JsonIgnoreProperties(ignoreUnknown=true)
public class ActivateService {
[...]
}
resource:
https://stackoverflow.com/a/39013609/8782229
Right now, all 404/500 results in a json error message.
How can I configure it so that on all 404/500 just redirect to a specific error page?
I've added the following to my initializer class:
#Bean
public EmbeddedServletContainerCustomizer containerCustomizer() {
return container -> {
container.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/error/errorpage"));
container.addErrorPages(new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/error/errorpage"));
};
}
But now it just redirects to a blank page...
Solution? I basically implemented the error controller and force all to redirect to errorpage. My errorpage is a jsp that lives right under WEB-INF/pages. Now is this correct?
#RestController
#RequestMapping("/errorpage")
public class SimpleErrorController implements ErrorController {
#Autowired
public SimpleErrorController(ErrorAttributes errorAttributes) {
Assert.notNull(errorAttributes, "ErrorAttributes must not be null");
}
#Override
public String getErrorPath() {
return "/errorpage";
}
#RequestMapping(produces = {"text/html"})
public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
response.setStatus(400);
return new ModelAndView("errorpage");
}
}
EDIT: You would likely need to remove your Bean definition for this to work, as I see you have added that after I have submitted my answer.
Add thymeleaf dependency to your pom:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
Depending on your spring boot version, add one of the two to your application properties file:
error.whitelabel.enabled=false
or
server.error.whitelabel.enabled=false
Create /src/main/resources/templates folder.
Add a file called error.html to this folder with the html you wish to display.
What we've done is use the thymeleaf templating engine to consume the default error.html file, and told Spring Boot not to use its default whitelabel error page.
I am using Spring 4.1.5 with Boot 1.2 on a webservice that does not serve up any JSPs. I don't want to add a JSP servlet but I want it to serve up a single canary page that shows in a prettier html type format the information that would be provided at the /manage/health endpoint.
I have a file in webapp/canary/canary.html I want to serve this up from the url: www.mywebservice.com:9343/canary, exactly like that, NOT canary.html
I tried doing this:
#Configuration
public class CanaryConfiguration extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/canary")
.addResourceLocations("/canary/canary.html");
}
}
That doesn't work however.
It is expecting the handler to provide a file name. So in otherwords the location should be something like: /canary/
and the handler would something like: /canary/**
With that, the URL www.mywebservice.com:9343/canary/canary.html would work like a charm.
HOWEVER, I want the URL to resolve www.mywebservice.com:9343/canary to webapp/canary/canary.html without me having to type the html.
This is really easy in a jsp servlet because you can set the suffix ect...
I looked at ResourceResolver but it didn't make sense to me how I would link that into my current configuration.
It looks like what I want:
Provides mechanisms for resolving an incoming request to an actual Resource and for obtaining the public URL path that clients should use when requesting the resource.
See: ResourceResolver Documentation
Any help would be very beneficial.
Also I am very aware that I can put html in the resources/static and several other places that are automatically configured. That always requires the .html to be typed, which is not what I want in this case so that won't work. Thanks!
You can use view controllers to do it. Here is a sample of it. Hope this helps.
public class AppConfig extends WebMvcConfigurerAdapter {
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/canary").setViewName("/canary/canary.html");
}
}
Note: if you are using tomcat, you might have to configure jsp servlet to server html files.
Related post here.
For information sake, the selected answer is the same as the following:
#Controller
public class CanaryController {
#RequestMapping(value="/canary", method=RequestMethod.GET)
public String getCanary() {
return "/canary/canary.html";
}
}
The above code will work as long as canary(or whatever file/folder) is in your webapp folder.
When I tried this I was trying to set the suffix to .html in my YAML (.yml) file and it wasn't working to I thought that it needed to return to a servlet if it is not a RestController. I was mistaken.
I m trying to create my first Spring application which is a simple REST webservice.
I want to make EVERY responses to be JSON (in the header) and I dont know how to make it in ONE time, I mean not in all my controller methods, like a config files or something else.
This is my code :
#RestController
public class HomeController {
#RequestMapping(value = "/something/{nom}/{id}", method = RequestMethod.GET)
public User hi(#PathVariable long id, #PathVariable String nom) {
return new User(id, nom);
}
}
Thanks for advance
Your method is correct. Since you are using Spring 4 and the annotation #RestController there's no need of using #ResponseBody.
In case you are not getting a JSON as return, please check if you have included Jackson Mapper dependency in your project.
You can do that by adding this on your pom.xml (presuming you are using Maven):
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.13</version>
</dependency>
By adding this dependency, Spring will be able to parse your object properly.