Is is recommended to use JSON Schema Validation in the place of Bean Validation JSR303 for Spring Boot Rest APIs? - spring-boot

Can we use JSON Schema Validation in the place of Java Bean Validation JSR303 for Spring Boot Rest APIs for Enterprise Applications? Which one is more efficient to validate request Payload to Spring Boot Rest APIs?
(i.e. performance wise, cross-validation wise and RegEx pattern based validation)

It is a good question and there are no definitive answers for it as, perhaps, it is dependent on the application domain and remains subjective to that. At the base level (which usually covers 90%) of all use cases of validating user input to the REST service, both have the equivalent facility to validate data adequately. Both support constraints which can be used to achieve the same result.
However, on one front Bean Validation stands out is its ability to define custom validators, which can be used to validate very specific domain/application dependent constraints. For example, if there is case where a class which has 3 attributes (say, A,B and C) and a constraint is required that is either A occurs or B & C occurs but not both, then it is not really possible to put a constraint in JSON schema directly, it has to be handled through design of the schema (similarly in XML, actually it is more complicated with XML).
On the other hand in Bean Validation a custom validator can be written to handle this situation quite easily.
However, these kind of cases are few and far between.
Another point to consider is the integration of the Bean Validation in the underlying framework e.g. Spring, Jersey, RESTEasy etc., JSON schema validation is not yet integrated in the frameworks.
Therefore, given the support for the tech, it is perhaps better to stick with Bean Validation 2.0 and leverage the underlying frameworks capability to validation (this is, however, purely my view).

From an application development prospect, Java bean validator is sufficient for the business needs. From a system integration point, JSON schema externalizes the business rules and provides a platform independent interface control. So if your system involves many subsystems, JSON schema gives a better way to verify message payload.

I prefer OpenAPI Specification, which can be regarded roughly as a JSON Schema dialect, to bean validation 2.0 (JSR380).
OpenAPI is the de-facto (correct me) standard to describe RESTful API today. There are tools for validation accroding to OpenAPI spec is available, an incomplete collection can be found at here. And of course it works well with Java/Spring.
OpenAPI validates JSON string rather than a POJO, thus it can handle the following case naturally while bean validation in Java cannot: say i want to validate the object in the request body of a PATCH request, and the object must have a property named A, while the value of A is can be null;
And there are more than validation you can do with an OpenAPI spec in your hand. Because an OpenAPI schema does not only define what the data model of RESTful API looks like, it also describes other aspects (endponts, parameters and status code etc.) of the API in the same file. Out there are a bunch of code generators to auto-generate server-side or client-side code to serve requests or retrive response in whatever language.

Related

Two approaches to implementing REST API on Spring

I do REST API on Spring. Took a course in Spring Data Hibernate and found that it made the REST API the most time-consuming way.
When I added a new entity to the domain, I went through the following chain of objects:
Entity - domain object
DTO - for transmitting/receiving an object to/from a client
Mapper - to convert between Entity and DTO
Repository - for interacting with the database
RestController - for processing API requests
Service - service class for the object
The approximate chain of my actions was as follows:
RestController processes requests - receives DTO from the client (in case of creation of a new object)
Mapper in controller converts DTO to Entity
Service is called
Service accesses the Repository
Repository returns the result of execution (created by Entity)
Service returns Entity is created in RestController
RestController returns to the client an object of type ResponseEntity, where I put the body and response code.
As you can see a large chain of actions and a large number of objects.
But then I found out that if you use Spring Data REST, all this doesn't need all the API supplied by Spring from the box. In general, you only need to create an Entity and Repository.
It turns out that for typical CRUD-type operations, I wrote a lot of controllers and their methods in vain.
Questions:
When should I use RestConroller, and when is Spring Data REST?
Is it possible to combine two approaches for one Entity? It turns out that I was wasting my time writing for simple operations like creating, getting, saving, deleting controllers, it can be moved to Spring Data REST.
Will I be able to implement some of the actions that I did in Spring Data Rest in RestConroller? Such as:
Return an entity property value as id instead of object? I mean I have properties for entities that are entities themselves, for these fields I sometimes need to return their ID instead of the whole entity.
Is there any way to control error handling? In RestController I have implemented the ResponseEntityExceptionHandler extension class and all errors wherever they occur in my RestController are handled in the same way in one place and I always know that all errors will return approximately the same response structure.
Data validation will have to be hinged on the fact that it used to be validated on DTOs received from the client. Are there any nuances waiting for me in this regard?
I'm a little stumped on how to move forward. Give me your recommendations and thoughts on this. Push forward on what to use and how.
What Spring Data REST can do for you is scaffolding of the plain repository to rest service. It is much faster, and in theory it should be flexible, but in practice it is hard to achieve something more than REST access to your repositories.
In production I've used Spring Data REST as a wrapper of the database - in a service/microservice architecture model you just wrap-up sometimes the core DB into such layer in order to achieve DB-agnostic Application. Then the services will apply the business logic on top of this wrapper and will provide API for the front-end.
On the other hand Spring Data Rest(SDR) is not suitable if you plan to use only these generated endpoints, because you need to customize the logic for fetching data and data manipulation into Repoitories/Services. You can combine both and use SDR for the "simple" entities, where you need only the basic CRUD over them, and for the complex entities to go with the standard approach, where you decouple the entity from the endopint and apply your custom business logic into the services. The downside of mixing up both strategies is that your app will be not consistent, and some "things" will happen out-of-the-box, which is very confusing for a new developer on this project.
It loooks wasted time and efforts to write these classes yourself, but it only because your app doesn' have a complex database and/or business logic yet.
In short - the "standard" way provides much bigger flexibility at the price of writing repetetive code in the beginning.
You have much more control building the full stack on your own, you are using DTO's instead of returning the entity objects, you can combine repositories in your services and you can put your business logic on the service layer. If you are not doing anything of the above (and you don't expect to in the near future) there is no need for writing all that boilerplate yet over again, and that's when Spring Data REST comes into play.
This is an interesting question.
Spring Data Rest provides abstraction and takes a most of the implementation in its hand. This is helpful for small applications where the business logic resides at the repository layer. I would choose this for applications with simple straight forward business logic.
However if I need fine grained control (eg: transaction, AOP, unit testing, complex business decisions etc. ) at each of the layers as you mentioned which is most often needed for large scale applications I will prefer writing each of these layers.
There is no thumb rule.

Spring MVC: Recommended way to validate things that require existing Services/Repositories

Spring MVC offers form validation through both annotations on the forms (for example #NotNull) to do a simple check of the value of a field, and custom Validators, which help you do cross-field validations (verifying two password fields contain the same value, etc).
I am looking for the recommended way to do validations that go a bit further, however. For example verify if a username is not used already, which requires a call to the database. I assume I can simply inject my PersonRepository into the custom validator (which is an #Component) after all, but I doubt it'll be transactionally safe..or very clean.
What is the recommended way to do this, that requires the least amount of duplicated code? Or should I simply write my own validation layer, that throws some ValidationException with a list of validationmessages, which I have to map to the bindingresult?
To just clearify: Spring MVC don't offers form validation by itself. It integrates with Java Bean validation vendors (like Hibernate Validator).
You're right: If you configure LocalValidatorFactoryBean as a bean in your application context, you benefit from dependency management in your custom validators. In my opinion there is no need to implement a custom validation layer within your setup, since you already have a powerful and generic abstraction of validation which even conforms to Java standards.
If you worry about whether calling your repository in validator is transaction safe or not see http://docs.spring.io/spring-data/jpa/docs/1.8.2.RELEASE/reference/html/#transactions for details. CRUD operations are transactional by default. If you need a more sophisticated validation logic with needs a transaction context, you could either make your isValid(...) method transactional by annotating it, or you could autowire a business service with likely is transactional by itself. This perfectly integrate with the concepts of Spring.
Use the same business transaction
If you need to handle validation and business logic (check whether a user name is already used and insert a new if not) in the same transaction you could think about restricting those validations in Controller layer to the basic ones (#NotNull for example). This will ensure, that only syntactic correct requests make their way to your service layer.
In the service you will use an autowired validator and trigger the entire validation constraints manually. If you have a combination Hibernate as JPA vendor and Hibernate as Validation vendor you could even make use of the integration of both (pre persit and pre update events) which will cause the validation to occur automatically before the changes are written to the database.
However you decide, you will likely use validation groups to split the constraints into two groups 'syntactic' and 'semantic' for example. If you call the validator manually you can pass the groups you want to take into account. If you use integrated validation with Hibernate you can control the groups for the different events by specifying the following properties:
javax.persistence.validation.group.pre-persist
javax.persistence.validation.group.pre-update
If you decide for this way you will simply call your transactional business service method from your controller. Business logic and validation will participate in the same transaction this way.

Business objects (DTO) in Spring Data JPA

By default Spring Data Repositories process database Entities. Please, suggest the standard approach of getting same functionality with Spring Data framework, which allows you operating on your Business Domain Objects (DTO) instead of Entities, and encapsulates all DTO to/from Entity mappings.
My current obvious options are:
Additional "proxy-wrapper" where all methods have same names as in Spring Repository but accept and return DTO types and encapsulate conversions(mappings).
Some clever implementation of previous option using AOP with less boilerplate code.
Both options seem pretty awkward to me for such a standard task. So, I assume I am jut missing something here.

Using java beans in AJAX

I am asking because I have only seen java beans used with a framework like struts or JSF.
Is it possible to send and access a java bean over an AJAX request?
Servlet myServlet creates and fills a java bean instance, and sets it in the request scope. An already loaded jsp/html page uses AJAX to request data from myServlet. Can this bean be accessed in any way? After thinking for a while, I have come to accept that this cannot be done.
If it can't be done, what would be the best practice when trying to transmit data from a model (i.e. user information from a database) asynchronously to a client when using Tomcat/Servlets and JSP?
It's technically possible if you serialize the javabean to a byte array or even a base64 encoded string using the usual Java Serialization API.
But how would it ever make sense to use a proprietary format to transfer data around? How would non-Java clients (e.g. JavaScript!) ever be able to consume the serialized Java object? These days XML, JSON and even CSV are much more widely supported and accepted. Practically every self-respected programming language has tools to easily convert between XML/JSON/CSV and the model as definied in the programming language in question. E.g. Java has JAX-RS API to easily convert between javabeans and XML or JSON. JavaScript has —obviously— builtin support for JSON (guess what "JS" in JSON stands for).
To learn and play around with the basic concept, head to this answer: How to use Servlets and Ajax?
To learn about the advantages of JAX-RS over servlet, head to this answer: Servlet vs RESTful
You can still use struts or jsf as you would normally to construct markup(html). And then consume the markup that was constructed via ajax and then append to the dom. If you are familiar with jQuery, something like jQuery('#selector').load('actionUrl.action');
But if you are looking to examine a java bean, then you will have to serialize it to xml or json. If you are using a web framework like struts2 or spring, there is likely a mechanism for doing this serialization for you. If you want to edit the bean you will have to serialize, then edit the serialized bean, and then deserialize back to the java bean.

struts2: accessing external service from type converter

is it possible to inject a service reference into custom type converter?
my situation is quite typical in fact, I have a combo, which binds to collection of entities. On submit I get only an ID of selected entity and have to refetch the real object in my action. I was thinking about more elegant way to do this, and it seems like making an ID-to-entity custom converter which would perform fetching - would be a good idea.
But I failed trying to map a converter to Spring bean in the same fashion like actions...
Interesting question. Are you using the spring plugin ?.
It is supposed to take care of service-objects creation, (and wiring with other services) for Struts2, and this should be able to include Type Converters. From here:
By using the struts2-spring-plugin in conjunction with type conversion, developers easily can use dependency injection to provide a converter with services
But I have not used that feature.

Resources