How to validate website URL field of an JPA entity? - java

I have a JPA entity representing a company. It has a field representing the company's website URL. I need to validate that the URL is a valid website URL prior to persisting. I suppose only URLs starting with http or https would be valid website URLs. How can I enforce this? I'm using the latest. version of Hibernate as my JPA provider.

#dimitrisli suggests you a correct solution. You should use #URL constraint. If you want to allow a specific protocol - there's a protocol attribute for this constraint:
#URL(protocol = "http")
private String companyUrl;
In addition there's also a regexp attribute which you can use to make your urls to match any pattern you'd like.
#URL(regexp = "^(http|ftp).*")
private String companyUrl;
You can check for more details in the doc (look for URL in the linked section).
Also if you'd like to use the URL instead of String, you can write your own validator implementation for URL class and URL constraint, but note if you'd try to create an invalid URL it will fail during creation process and not when validated. So writing a validator for URL might make sense only if you'd like to check the protocol and things like that.
To write your own validator you would need to implement
public class URLValidator implements ConstraintValidator<org.hibernate.validator.constraints.URL, URL> {
...
}
for more details check out this blog post.

Take a look at the #URL annotation of Hibernate Validator.

Related

How to use Basic Authentication with Spring's Resource abstraction

I have a file on a server available via Https I want to access using Spring's Resource abstraction. I want Spring to resolve the resource and inject it into the constructor of my Bean like this:
public class MyClass {
public MyClass(
#Value("https://myserver.com/myfile") Resource resource) {
// do something using the resource
}
}
The issue is that I cannot figure out how to include the username and password for basic authentication into this pattern. I tried the "common" style
#Value("https://username:password#myserver.com/myfile")
but it looks like this is not understood correctly. The server is responding with HTTP status 401 - Unauthorized. I copied the string and perfomed the same query using wget and it worked. So there is no issue with my credentials but most likely with the syntax used to define the resource.
Is there a valid syntax for this in Spring or must I fetch the config in an alternative way setting the Authentication header by hand?
This feels wrong, and I'd prefer it if you didn't do it this way...but you can rely on #Value to inject the property value. Note the use of #Autowired here.
#Component
public class MyClass {
private String resourceUrl;
#Autowired
public MyClass(#Value(${external.resource.url}) String resourceUrl) {
this.resourceUrl = resourceUrl;
}
// The rest of your code
}
Then you could place into the property external.resource.url whichever value you liked...including your full URL with username and password.
I want to call attention that this is probably not a desirable thing to do, since you want to be able to inject the URL, username and password as separate things into your application. This gives you an idea of how you can accomplish it with one component, and while I strongly encourage you to split this up instead (and whatever you do, do not check the properties file in with those values into your source control), I leave the mechanical part of splitting this into more values as an exercise for the reader.

Spring Data Rest: how to transform all urls in Kebab Case?

I want to use spring-data-rest to expose my repositories via an API. URLs are generated from domains name. Those URLs are camelized.
For example, considering domain named EntityA, the associated url and rel will be entityA (in camelCase).
How can I configure spring-data-rest (or what have I to override) to get kebab-case by default ? (for example, entity-a instead of entityA)
I know that I can use #RestRepository and provide URLs for each repositories. But I'm looking for better solution. I want to use kebak-case for entities and searches methods.

Accessing Parameters mapped by #RequestMapping for Tracing

I am currently working on a monitoring application using Spring Cloud Sleuth. Currently I try to collect as much information about my requests as possible.
To keep the approach as scalable as possible I use GenericFilterBeans and HandlerInterceptorAdapter to access information from the requests sent to the REST-API.
I am struggling with getting parameters of a REST-call where the parameters are mapped from the URL like in the following code snippet:
#RequestMapping(
value = {"/{service}/{route_id}/book", "/accounting-core-service/{service}/{route_id}/book"},
method = RequestMethod.GET)
#ResponseBody
public ModelAndView book(#PathVariable(value="service") String serviceName,
#PathVariable(value = "route_id") int routeId,
HttpServletResponse response) {
/*Do something*/
}
The question is not, whether it is good practice or not to write it like so. The question is whether there is an approach similar to Filter or Interceptor (or the proper use of them) to access those parameters.
A requirement is, that it can be applied easily to an application by adding very few lines of code. Annotating every Method call manually or manually inserting the code to write the parameters into the trace from within the method is not feasible for me.
If you need more information feel free to ask. I will provide you with all information you need to help me with my problem.
Although not officially supported (as it's not written in the reference documentation), Spring MVC holds that information as request attributes.
You could create your own HandlerInterceptor, ordered right after the Sleuth one, and get that information from the request like this:
// "/{service}/{route_id}/book"
String matchingPattern = (String) request
.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
// "service" => "fooService", "route_id" => "42"
Map<String, String> templateVariables = (Map<String, String>) request
.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
Note, the template variables are already decoded at that point, which is probably what you want anyway.
You can create a Filter that intercept all the requests.
For each request you can retrieve also this informations:
query parameters
body of request
url
header parameters
You can save all this data as you need.
This is the best way you can do that.
If you need to group all urls like /{service}/{route_id}/book in a "family" of urls you can do that splitting the url and check if it is part of the family, but when a new family is added in your code you need to update the filter (or configure something in an external file or database).

Manipulate #FormParam for sanitizing XSS values

I am using #FormParam from jsr311-api-1.0.jar in an old project with Jersey 1.0.3. Is there a way to add a filter which sanitizes and changes all the #FormParams that I am using in the application?
Example code is as follows:
#POST
#Path("myMethod")
public String myMethod(#FormParam("data") String data) {
// Need to change the value of this data to clean XSS
// Code to save data into database
}
Since the JAX-RS 1.0 API (JSR 311) do not provide filters or interceptors, you could consider sanitizing the input in your resource methods.
To do it, you could consider jsoup. Here is an example provided by the documentation:
String unsafe =
"<p><a href='http://example.com/' onclick='stealCookies()'>Link</a></p>";
String safe = Jsoup.clean(unsafe, Whitelist.basic());
OWASP Java HTML Sanitizer can do the trick too. Here is an example provided by the documentation:
PolicyFactory policy = new HtmlPolicyBuilder()
.allowElements("a")
.allowUrlProtocols("https")
.allowAttributes("href").onElements("a")
.requireRelNofollowOnLinks()
.toFactory();
String safeHTML = policy.sanitize(untrustedHTML);
If you are willing to use the Jersey API, it's worth mention that Jersey 1.x provides the ContainerRequestFilter interface that you can implement and modify the state of the request.

How to put and post links with Spring HATEOAS

I'm trying to understand how to create and modify links in Spring HATEOAS.
For example, say I have two collections, one at api/users and another at api/event. I would like to associate a user api/user/56 with an event api/event/21. For arguments sake this is a many-to-many - a user may attend many events, an event may have many users.
As I understand it, the restful way of doing this is to use the URIs as primary keys, so I might post the following to api/user/56/events;
{
attends: "http://localhost:9090/api/event/21"
}
The endpoint then needs to be able to parse that URL and extract the ID (in this case 21) and the controller (EventController.class) so that I can persist this.
Question 1: Is this the correct way of dealing with relationships in Spring Hateoas in terms of the REST API?
Question 2: How can I resolve this url in a controller to a usable handle on the data (for example a reference to the appropriate controller/method, a primary key, etc)
Research
RestTemplate can be used to request the data from the controller inside the request mapped method, like so;
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<EventResource> response = restTemplate.getForEntity(attendsUrl, EventResource.class);
EventResource eventResource = response.getBody();
However I don't believe that eventResource should return an Id field as part of the data - it's not very restful and this would be exposed on the API. One approach is to have a parameter "includePK=true" but again this doesn't feel right - it's just hiding the problem. Moreover the idea of the server making requests to it's own API in this manner seems circuitous.
Update
There is an open question for this here https://github.com/spring-projects/spring-hateoas/issues/292. Based loosely on some of the comments (by user kevinconaway) from that issue I have made a quick util class that offers an easy solution here: SpringHateoasUtils. The solution boils down to;
String mapping = DISCOVERER.getMapping(targetClass, targetMethod);
UriTemplate template = new UriTemplate(mapping);
//values is key/value map of parameters that the referenced method accepts
Map<String, String> values = uriTemplate.match(uri);
SpringHateoasUtils makes this slightly nicer but it still feels like it should be a feature. I'll seek to get something in the spring code for this - when it's clear what is happening with this I'll answer this question.
Look at the answer here:
POSTing a #OneToMany sub-resource association in Spring Data REST
Question 1) Yes this is how you post links/relations. With URIs.
Question 2) The URI of the resource actually IS its ID from the client's perspective. The server internally automatically resolves this URI into the actual model instance with
org.springframework.data.rest.core.UriToEntityConverter.convert(...)

Categories

Resources