Regex in #RequestMapping - regex

I have got stuck with the following. Lets say I have an url like
http://localhost:8080/a/somename-anyothername-onemorename-aAttributeId.html
http://localhost:8080/a/anyothername-onemorename-aAttributeId.html
http://localhost:8080/a/anyothername-onemorename-anyothername-anyothername-aAttributeId.html
...
In general the url may have a number of parts. My goal is to set the AttributeId part of the url above as a variable in #RequestMapping as it shown below
#Controller
#RequestMapping(value = "/**/a")
public class ProductPageController extends AbstractPageController
{
#RequestMapping(value = "/{attributeId:(?:[-a])(?!.*(?:[-a])).*}.html", method = RequestMethod.GET)
public String requestHandler(#PathVariable("attributeId") final String attributeId, final Model model) {
//method body
}
}
}
My question is what I do wrong with my regex? Should I split the regex somehow to escape everything before the aAttributeId.html part as the following:
#RequestMapping(value = "/{unused:*.}{productCode:(?:[-a])(?!.*(?:[-a])).*}.html", method = RequestMethod.GET)
Thanks for ideas
Update: Answer for the question
The final mapping looks as the following:
#RequestMapping(value = "/**{attributeId:a(?:[^-]+)}.html", method = RequestMethod.GET)

How about:
-a([^-]+)\.html
NB: I don't know spring syntax.

Related

spring boot - why is #valid not working on controller for type?

I have Spring Boot application with a rest endpoint in a #RestController annotated class that is something like this:
#Postmapping(path = "<url>")
private #ResponseBody ResponseEntity<?> methodName(
otherParameters otherParameters,
#Valid #RequestBody Entity entity,
Errors errors) {
if(errors.hasErrors()) {
// log something
// do something
}
// rest of the controller
}
The Entity class is something like this:
public class Entity {
#Pattern(regexp = "[^<>&]+")
private String someString;
// getters and setters
}
But when I try to reach the controller with someString as some&tring, the #Valid annotation does not seem to work.
This is accessible only from a rest call. There are no forms that use this action.
There is no spring-security implementation in this application at the moment.
What am I missing here?
Be sure to add #Valid on the member fields of your pojos if those fields represent pojo's themselves, otherwise the validation does not propagate.
I think you are missing the object add to the page.
check the following code.
check 1 :
// on controller side
#GetMapping("/registration")
public String registration(Model model) {
model.addAttribute("entity", new Entity());
return "registration";
}
#PostMapping("/registration")
public String registration(#ModelAttribute("entity") Entity entity, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
return "registration"; // stay on that page here
}
return "login"; // after no error go here
}
use this entity in form on the page where you want to access the validation
<form action="#" th:action="#{/registration}" th:object="${entity}" method="post" class="m-t">
check 2 :
both the get and post method must be the same name for the object created like **entity**

How to match only paths in /[^/]+ with Spring #RequestMapping?

I need the following:
Any request to
https://localhost:8443
https://localhost:8443/
https://localhost:8443/test
https://localhost:8443/api
and so on, should be forwarded to
https://localhost:8443/a/web/index.html
Now, this is how I managed to do that:
#Controller
public class ForwardController {
#RequestMapping(value = "/*", method = RequestMethod.GET)
public String redirectRoot(HttpServletRequest request) {
return "forward:/a/web/index.html";
}
}
The problem is:
This also matches https://localhost:8443/api/ (note the / at the end).
This is a problem because that's where I want the Spring Data REST base path to be:
spring.data.rest.base-path=/api/
/api != /api/ when it comes to REST endpoints.
What should work but somehow doesn't
I have tried several different regular expressions but I am still not able to accomplish what I want. For example (demo):
#RequestMapping(value = "/[^/]+", method = RequestMethod.GET)
Will now work for Spring Data - I'm getting all the resource information I expect, but accessing https://localhost:8443/ is now broken and the web-client cannot be reached anymore.
The same goes for
#RequestMapping(value = "/{path}", method = RequestMethod.GET)
#RequestMapping(value = "/{path:[^/]+}", method = RequestMethod.GET)
which behave like /* (also matches the next /).
This issue is already haunting me for weeks and still no solution insight.
This whole question can also be seen as:
Why is "/[^/]+" not matching https://localhost:8443/whatever ?
Regex are usually not the fastest thing to try.
You can send a list of paths to
#RequestMApping(value={"", "/", "/test", "/api"}, method = RequestMethod.GET)
See Multiple Spring #RequestMapping annotations

How to create an instance of HttpServletRequest for unit testing?

While doing some searches on SO I came across this piece of code to extract the "appUrl" from a URL:
public static String getAppUrl(HttpServletRequest request)
{
String requestURL = request.getRequestURL().toString();
String servletPath = request.getServletPath();
return requestURL.substring(0, requestURL.indexOf(servletPath));
}
My question is how does one unit test something like this? The key problem is how to create an instance of HttpServletRequest for unit testing?
Fwiw I tried some googling and most of the responses center around mocking the class. But if I mock the class so that getRequestURL returns what I want it to return (taking an example since mocking essentially overrides some methods to return canned values), then I am not really testing the code at that point. I also tried the httpunit library but that also does not help.
I use mockito and here is the block of code in the test method I use to mock it up:
public class TestLogin {
#Test
public void testGetMethod() throws IOException {
// Mock up HttpSession and insert it into mocked up HttpServletRequest
HttpSession session = mock(HttpSession.class);
given(session.getId()).willReturn("sessionid");
// Mock up HttpServletRequest
HttpServletRequest request = mock(HttpServletRequest.class);
given(request.getSession()).willReturn(session);
given(request.getSession(true)).willReturn(session);
HashMap<String,String[]> params = new HashMap<>();
given(request.getParameterMap()).willReturn(params);
// Mock up HttpServletResponse
HttpServletResponse response = mock(HttpServletResponse.class);
PrintWriter writer = mock(PrintWriter.class);
given(response.getWriter()).willReturn(writer);
.....
Hope that helps, I use this to test methods that require servlet objects to work.

Spring 3 MVC Web services: many parameters with same name

I am running into the next problem. I have declared a method in the controller like the next one, to be used as a web service:
#RequestMapping(value = "/" + "prueba" , method = RequestMethod.GET)
public void prueba(ExampleBean pExample1, ExamlpleBean pExample2) {
// Wonderful code here
}
And the class ExampleBean is just, well, a Bean:
public class ExampleBean implements Serializable {
private String id;
private String whatever;
// getters, setters, and more.
}
If the interface were something like that:
#RequestMapping(value = "/" + "prueba" , method = RequestMethod.GET)
public void prueba(ExampleBean pExample1) {
// Wonderful code here
}
Each time I would like to call that web service, I would call the URL in the next way:
http://myWebProject/prueba?id=1&whatever=hola
But... How can I do when I have to give values to both params from the same class? I mean, I can not repeat parameters, so I dont know how to differ between the id from pExample1, and the id from pExample2 when writing the URL.
I mean, also with two parameters from different classes, but with an attribute with the same name. For example, if the second parameter is from the class DifferentExampleBean, which has also an "id" parameter.
Thanks a lot!
PS: I am using StringHttpMessageConverter.
What you would do is to create a parent class which would hold particular field you're interested in then both ExampleBean and ExampleBean1 would extend this parent class and you'd have only one type to be sent in prueba(ParentClass instance1, ParentClass instance2).
Where instance1 would be instance of ExampleBean and instance2 would be instance of ExampleBean2

RegularExpressionAttribute Not Working and I Don't Know Why

I have a simple view model class for MVC2 that has a MagicItem property:
public class VoodooViewModel {
[Required(AllowEmptyStrings = false,
ErrorMessage = "The Magic Item is required")]
[RegularExpression(#"^[^-]*$",
ErrorMessage = "Hyphens are not allowed in Magic Items.")]
public string MajorModel { get; set; }
}
I am simply trying to disallow hyphens in this property, but for the life of me I can't get it to work. Can anyone see what I'm doing wrong (the RequiredAttribute is working fine)?
To my eyes, the regex I have says "from the beginning of the string to the end, match anything that isn't a hyphen". I have tested this in the Regex tester here, and it works - but not in my code. I can't get the error to show no matter how many hyphens I put in it.
Like a tool, I forgot to check in the controller's action method to see if the ModelState was valid or not:
public ActionResult UberController(VoodooViewModel vvm)
{
if (!ModelState.IsValid) return View(vvm); //turns out this line is important
(...yaddayaddayadda...)
}
Thanks to Darin for pointing me in the right direction.