We have an application with path pattern like this:
/{language}/{subsystem}/blah/blah
the language and subsystem variable will do some common logic and apply to all 100+ controllers, i wanna ask instead of repeating this common logic 100 times in each controller, is there a way to define a centralized controller like
/{language}
which is to handle the language logic and another centralized controller like
and /{subsystem}
which is to handle the subsystem logic and all other controller kinda of 'extend' from these controllers ?
Hope i describe it clearly. many thanks and happy weekend:)
You could think about writing a custom Interceptor for your application. This interceptor could fetch the language and subsystem parts from your URL path and invoke your common logic in a central place.
There are a few pitfalls to this approach that you should balance carefully:
it's very implicit - people might miss that your interceptor is in place and could be in for a surprise
it'll apply for all incoming requests - if you want it to skip certain requests, you have to implement this logic within the interceptor
Personally, I'd take another approach and go for a combination of #RequestMapping and #PathVariable annotations on every controller method to capture language and subsystem and put the common logic into a helper method:
#GetMapping("/{language}/{subsystem}/something")
public String doSomething(#PathVariable Language language, #PathVariable Subsystem subsystem) {
LanguageSubsystemHelper.doSomething(language, subsystem);
// ...
}
Reduce the repetition to a minimum by providing a helper that's available for all controller methods. The benefits of this approach are:
you have granular control when to use or not use the common logic
it's explicit
you can automatically validate language and subsystem by binding the path variables to an enum
Related
I was looking for a way to make my JAX-RS APIs more readable and came across with Google's Custom Methods approach:
https://cloud.google.com/apis/design/custom_methods
I was looking for this because some of my entities perform more actions than I could express with traditional HTTP verbs. Google pattern is to use a colon (:) at the end of the URI, separating the entity/collection from the desired action.
I tried to apply this pattern to a simple Jersey resource, just to test how it could be done. I've got a resource class StudentDetailsResource annotated with #Path("students/{studentId}") and a few methods also annotated with #Path.
If my method has another entity before the custom method, then all is ok. Let's say the enrol method is annotated with
#Path("subjects/{subjectId}:enroll").
The problem rises when the action is right after the Resource Class URI, because #Path uses a URI Template that prefixWithSlash all sub-resources. So if I have a dropout method, the annotation would look like #Path(":dropout"), but the URI template would become /students/{studentId}/:dropout, an this /: would break in the matching phase.
I have read about Jersey Providers and ResourceDelegates, but I couldn't find a way to replace the URI Template default action of prefixWithSlash.
The question is: how can I apply Google's custom method approach or how can I avoid the default prefixWithSlash behaviour with Jersey?
Note: I know this is a silly example and there are other ways to solve this specific case, but I have more complex cases which can benefit from the custom methods.
I am using spring rest controller to implement my web api, I want to put my common methods between controllers in one place so can be used in all my controllers.
If there is no way to extend #RestController annotation, Is it a good practice to write controller common methods in a parent Class BaseController and extend all my controllers from it ?
You could create your own stereotype/annotation but it would clearly be an overhead if you want only add some common methods to the controllers. Besides, you will make your code less "Spring standard". I don't think that you want that.
Is it a good practice to write controller common methods in a parent
Class BaseController and extend all my controllers from it ?
I don't think that it is a bad practice but here some scenarios where I don't want to use class inheriting for controllers :
The common code looks like logic while controllers should not perform logic but delegate. If these make too much things, introduce a service class and delegate to it.
if controllers don't share a set of common fields/dependencies/initializations, using a dependency class that provides the common methods would be probably clearer/simplest. Creating a hierarchy of classes to avoid declaring a common field seems too much and a subclassing abuse.
you should favor Spring AOP and ControllerAdvice for common processing in controllers for pre/pro/processing and exception handling.
If you don't fall into these cases, yes an abstract class for your controllers looks a good idea.
If I understand correctly, what you're looking for is a service layer. It can be used to store all of your business logic and common methods you might need. You extract them and inject the service object into your controller. From there you simply call your methods from the service layer and do not pollute your controller. It's considered a good practice to do so, from my experience.
Another thing you could do for methods that can be used for different kinds of controllers that have nothing in common is, as you said, can be extracted to a Utility class. You can fill this class with static methods you can use across your application.
My controllers require common functionality like
-inspecting parameters on incoming requests
and
-including headers in outgoing response.
In order to avoid boilerplate of parent/child controllers invoking each other, I took advantage of spring annotations/hooks.
To parse and validate request parameters I went the route of
a controller advice class and annotating a method therein with #ModelAttribute
-which spring calls before the route methods
and
-which you can use to make objects available in the model.
To include headers in all responses I went the route of extending ResponseBodyAdvice where using custom annotations, you can the controller mapping method to indicate to the controller advice whether it should be invoked for that response.
The weak point here for me is communicating from controller to the advice for the response.
I went the route of the custom-annotated controller mapping method setting an attribute in the request for later use in the response advice (and documenting that annotated methods are expected to do so.)
All of the code samples of Spring Boot and Jersey that I have seen register their components with Jersey by passing the component's class.
From here:
public static class JerseyServletConfig extends ResourceConfig {
public JerseyServletConfig() {
register(RequestContextFilter.class);
packages("com.github.cthiebault");
register(LoggingFilter.class);
}
}
Or here:
register(ApiListingResource.class);
ResourceConfig's javadoc says:
Register an instance of a custom JAX-RS component (such as an
extension provider or a feature meta-provider) to be instantiated and
used in the scope of this configurable context.
My questions are:
What is the benefit of letting those resources being instantiated by Jersey?
If we should let Jersey manage those components, why does it still provides a register(Object component) method, why not keep it limited to register(Class<?> componentClass)?
When should we send our own instances instead of letting Jersey instantiating our class?
To start, Dependency Injection is a GoodThing(tm) in general - it allows for separating concerns and it can greatly simplify testing. In general separating object creation from object use gives benefits around separating business/application logic (i.e. object use) from implementation concerns (deciding what objects are wired together).
Allowing Jersey to manage your resources / components is also a GoodThing(tm). It's a part of what Jersey is for. If you allow Jersey to manage your resource lifecycle then you have less code to write / maintain and the code which you do end up writing / maintaining becomes more about what your application does and less about how your objects fit together.
Jersey provides a standard lifecycle, which gives you a convention that allows developers a mental framework to work in - making it easier for new developers to join and existing developers to switch between applications. The lifecycle can be configured if need be, which allows your special-snowflake application to have special-snowflake behaviour if necessary.
The register(Object) method is an example of how you can opt-out of Jersey controlling a component's lifecycle. You may want to do that for lots of reasons, but you should generally look to avoid doing it - let the library do its job. Examples of exceptional cases would be if you're integrating with some legacy code which, for obscure/arcane reasons of its own, means that some crucial class must be an application-level singleton. There may even be some non-legacy reasons why you only want a single instance of something in your application - object mappers were always a good example of this. Typically, you'd use JSR-330 support for that nowadays but there might be some cases where that's not possible.
By integrating with JSR-330, you can also provide custom named scopes for some objects - which allows you to control how Jersey creates and uses objects while also revealing what you're intending (via the scope name). This generally provides a clean structure which is intention-revealing rather than intention-hiding.
This question is about a specific usage of a callback pattern. By callback i mean an interface from which i can define method(s) that is (are) optionnaly (= with a default set to 'do nothing', thanks Java 8) called from a lower layer in my application. My "application" is in fact a product which may have a lot of changes between client projects, so i need to separates somethings in order to reuse what won't change (technical code, integration of technologies) from the rest (model, rules).
Let's take an example :
I developped a Search Service which is based upon Apache CXF JAX-RS Search.
This service parses a FIQL query which can only handle AND/OR condition with =/</>/LIKE/... condition to create a JPA criteria query. I can't use a a condition like 'isNull'.
Using a specific interface i can define a callback that will be called when i got the criteria query from apache CXF layer in my search service and add my condition to the existing ones before the query is executed. This condition are defined on the upper layer of my searchService (RestController). This is in order to reduce code duplicate, like retuning a criteria query and finalize it in every methods where i need it. And because using #Transactional in CXF JAX-RS controller does not work well Spring proxy and CXF work (some JAX-RS annotation are ignored);
First question : does this example seems to be a good idea in terms of design ?
Now another example : i have an object which have some basic fields created from a service layer. But i want to be able to set others non-nullable fields not related to the service's process before the entity is persisted. These fields may move from a projects to another so i'd like to not have to change the signature of my service's method every time we add / remove columns. So again i'm considering using a callback pattern to be able to set within the same transaction and before object is persisted by the Service layer.
Second question : What about this example ?
Global question : Except the classic usage of callback for events : is this a pratice to use this pattern for some specific usage or is there any better way to handle it ?
If you need some code sample ask me, i'll make some (can't post my current code).
I wouldn't say that what you've described is a very specific usage of "an interface from which i can define method(s) that is (are) optionally called from a lower layer". I think that it is reasonable and also quite common solution.
Your doubts may be due to the naming. I'd rather use the term command pattern here. It seems to me that it is less confusing. Your approach also resembles the strategy pattern i.e. you provide (inject) an object which performs some calculations. Depending, on the context you inject objects that behave in a different way (for example add different conditions to a query).
To sum up callbacks/commands are not only used for events. I'd even say that events are specific usage of them. Command/callback pattern is used whenever we need to encapsulate an operation within an object and transfer/pass it somehow (by the way, in Java there is no other way to do so but for example in C++ there are pointers to methods, in C# there are delegates...).
As to your second example. I'm not sure if I understand it correctly. Why can't you simply populate all required fields of an object before calling the service?
I wanted to know if ServiceFacade Design Pattern is really required while consuming a web-service.
http://soapatterns.org/design_patterns/service_facade
Any insight and code snippet would be really helpful.
Thanks in advance !!
The aim of the facade is to provide a forward (or client) facing endpoint, which in turn provides only what is needed for communication and hide anything which is behind it to the outside world.
Having a facade will allow you to abstract your behaviour without exposing it. It will also allow you to make changes without potentially affecting the endpoint itself. That depends on the type of changes obviously, but if you have some requirements which require some change in the logic it might be possible that the actual input and output of the service remain untouched.
If you where to do away with the service facade, any changes to the code might require your clients to update the code from their end, and those who, for some reason do not update might end up with a broken system or else you would have to cater for multiple versions.
Service Facade design pattern is not mandatory consuming a web-service. it is required when you don't want to expose core service contract changes.
How it works
You will define a core business service contract (CoreServiceContract)
You will define implementation for that contract (CoreServiceContractImpl)
You will define one service facade which is customer facing ( ServiceFacade )
This ServiceFacade holds the reference of contract - CoreServiceContract
You will invoke methods defined in CoreServiceContract through ServiceFacade. CoreServiceContract holds implementation of CoreServiceContractImpl
Advantages:
1) The Service Facade insulates the service definition from its implementation.
2) It is the way of decoupling the Web tier from the Business tier.
3) From a transactional point of view, the business service may implement his transaction scope or be part of the current transaction.
4) The contract of the Service Facade interface is oriented to be invoked by Web tier or client software, but methods of the contract should not be invoked
within the business implementation.
Have a look at this article for working code