Java EE REST Path levels to array - web-services

I have to following URI which outputs categories and subcategories:
Pattern:
www.uri.com/webservice/category1/category2/category3/category4
Example:
www.uri.com/webservice/1/56/104/605
This URI can have none,one or more subcategories like in the example.
How do i get these parameters (1,56,104,605) in an array so i can check if each category is a subcategory of the other?

Inject an UriInfo instance in your resource method and use the getPathParameters() or getPathSegments() method:
#Path("category/{categoryIds:.+}/product/{productId}")
public ReturnType myMethod(#Context UriInfo uriInfo) {
for (PathSegment pathSegment: uriInfo.getPathSegments()) {
//do here what you want with the uriInfo
}
}

Related

How to create a list of values inside application.properties file and how to retrieve that list inside controller class using springboot

My requirement is to create a list of values inside application.properties file.
com.mail = aaaa, bbbb, cccc
I want to retrieve these values in my controller class and iterator over each value and should check with the requestbody/queryparam values which gets, when hitting an API
Consider I have an API
#RestController
#RequestMapping("/response")
public class HomeController {
#PostMapping("/postbody")
public String postBody(#RequestBody String fullName) {
//here I have to validate the fullName with the list I created in the application.properties
Eg: if(fullname.equals(aaaa) or if(fullname.equals(bbbb) or if(fullname.equals(cccc)
// I want to iterator over the list to check any value is matching with fullName.
}}
How to declare list of values inside application.properties? How to retrieve that list inside controller class? Post retrieving how to iterate over the list to check whether it matches with requestbody/queryparam value?
Please provide me with solution. Thank you
Split the list using a comma as the delimiter.
private String[] mailList;
public HomeController( #Value("${com.mail}") final String mail) {
mailList = mail.split(",")
}
You can now use mailList inside postBody method.
use comma separated values in application.properties
com.mail = aaaa, bbbb, cccc
Java code for access
#Value("${com.email}")
String[] mailList;
It worked.
In Application. properties you will add the parameter with values separated with ','
com.mail = aaaa,bbbb,cccc
in the controller will get the Values
#Value("${com.mail}")
private List<String> mailListValues;
#RestController
#RequestMapping("/response")
public class HomeController {
#Value("${com.mail}")
private List<Object> mailListValues;
#PostMapping("/postbody")
public String postBody(#RequestBody String fullName) {
if(!mailListValues.isEmpty()){
long countOfMatch = mailListValues.stream()
.filter(item->item.equals(fullName)).count();
if(countOfMatch >0)
// your Business .....
}
}}
please check images

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**

RestEasy : GET request with multiple dynamic arguments

The required URL should be something like this :
http://<host>:<port>/path/item?<arguments>
The arguments key and value supposed to be multiple and dynamic, so I cannot use #BeanParam or #QueryParam. Also I can only call this interface without implementation.
My current code is something like this :
public interface RestService {
#GET
#Path("/path/item")
#Produces(MediaType.APPLICATION_JSON)
public JsonNode method(#QueryParam("params") String params);
}
Example of arguments that I want to pass : brand=myBrand&price=myPrice
Is there any way to do something like this ?
My References :
REST Web Service - Dynamic Query Parameters
Passing indefinite Query Parameters with RESTful URL and reading them in RESTEasy
Use UriInfo.getQueryParameters(), as following:
#GET
#Path("/path/item")
#Produces(MediaType.APPLICATION_JSON)
public JsonNode method(#Context UriInfo uriInfo) {
MultivaluedMap<String, String> queryParams = uriInfo.getQueryParameters();
...
}
It returns a MultivaluedMap. Then just iterate over it.

Swagger, Endpoints and Pathparameters

TLDR: Multiple Pathparameters and Endpoints with Swagger
What i would like to to is some API Endpoint like this:
/foo/{id}/bar
Now afaik foo or the first node in the path is defining the endpoint and also the resource to aqcuire. Therefore a FooApiServiceImpl is generated.
The generated ProjectsApiService stub looks like this atm:
#GET
#Path("/{id}/bars")
...
public Response getBarsByFooId(#ApiParam(value = "The id of the foo with the bars",required=true ) #PathParam("id") String id)
throws NotFoundException {
return delegate.getBarByFooId(id);
}
Now my wished behaviour would be to GET all the Bar resources that are connectted to the Foo with the given {id}. Kinda like the reverse order. Is this somehow possible?
If this is not possible... then would also like to ask, how can i get url nodes (foo, bar) that are not defined as {xxx} paramaters in brackets?
Something like this:
public Response getBarsByFooId(String foo, String id, String bar)
throws NotFoundException {
return delegate.getBarByFooId(id);
}
To get the paths segments, inject a UriInfo in your resource class or method:
#Context
private UriInfo uriInfo;
And then invoke UriInfo.getPathSegments() from it:
List<PathSegment> segments = uriInfo.getPathSegments();
See the UriInfo.getPathSegments() documentation:
Get the path of the current request relative to the base URI as a list of PathSegment. This method is useful when the path needs to be parsed, particularly when matrix parameters may be present in the path. All sequences of escaped octets in path segments and matrix parameter values are decoded, equivalent to getPathSegments(true).

How can I set a RegularExpression data annotation's regular expression argument at runtime?

We manage several ASP.NET MVC client web sites, which all use a data annotation like the following to validate customer email addresses (I haven't included the regex here, for readability):
[Required(ErrorMessage="Email is required")]
[RegularExpression(#"MYREGEX", ErrorMessage = "Email address is not valid")]
public string Email { get; set; }
What I would like to do is to centralise this regular expression, so that if we make a change to it, all of the sites immediately pick it up and we don't have to manually change it in each one.
The problem is that the regex argument of the data annotation must be a constant, so I cannot assign a value I've retrieved from a config file or database at runtime (which was my first thought).
Can anyone help me with a clever solution to this—or failing that, an alternative approach which will work to achieve the same goal? Or does this just require us to write a specialist custom validation attribute which will accept non-constant values?
The easiest way is to write a custom ValidationAttribute that inherits from RegularExpressionAttribute, so something like:
public class EmailAttribute : RegularExpressionAttribute
{
public EmailAttribute()
: base(GetRegex())
{ }
private static string GetRegex()
{
// TODO: Go off and get your RegEx here
return #"^[\w-]+(\.[\w-]+)*#([a-z0-9-]+(\.[a-z0-9-]+)*?\.[a-z]{2,6}|(\d{1,3}\.){3}\d{1,3})(:\d{4})?$";
}
}
That way, you still maintain use of the built in Regex validation but you can customise it. You'd just simply use it like:
[Email(ErrorMessage = "Please use a valid email address")]
Lastly, to get to client side validation to work, you would simply add the following in your Application_Start method within Global.asax, to tell MVC to use the normal regular expression validation for this validator:
DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(EmailAttribute), typeof(RegularExpressionAttributeAdapter));
Checkout ScotGu's [Email] attribute (Step 4: Creating a Custom [Email] Validation Attribute).
Do you really want to put the regex in database/config file, or do you just want to centralise them? If you just want to put the regex together, you can just define and use constants like
public class ValidationRegularExpressions {
public const string Regex1 = "...";
public const string Regex2 = "...";
}
Maybe you want to manage the regexes in external files, you can write a MSBuild task to do the replacement when you build for production.
If you REALLY want to change the validation regex at runtime, define your own ValidationAttribute, like
[RegexByKey("MyKey", ErrorMessage = "Email address is not valid")]
public string Email { get; set; }
It's just a piece of code to write:
public class RegexByKeyAttribute : ValidationAttribute {
public RegexByKey(string key) {
...
}
// override some methods
public override bool IsValid(object value) {
...
}
}
Or even just:
public class RegexByKeyAttribute : RegularExpressionAttribute {
public RegexByKey(string key) : base(LoadRegex(key)) { }
// Be careful to cache the regex is this operation is expensive.
private static string LoadRegex(string key) { ... }
}
Hope it's helpful: http://msdn.microsoft.com/en-us/library/cc668224.aspx
Why not just write you own ValidationAttribute?
http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.validationattribute.aspx
Then you can configure that thing to pull the regex from a registry setting... config file... database... etc... etc..
How to: Customize Data Field Validation in the Data Model Using Custom