Spring overwriting controller - spring

I provide a highly customisable application to my clients which is working totally by itself. But If one my client wants to overwrite any Controller, I want to replace my implementation by theirs. However just overwriting the controller causes an ambiguous definition of mappings.
I have been using Component Scanning to load beans.
The potential solutions came to my mind are:
Using component scanner with excluding by a custom filter? (This seems not so easy)
Using a xxxxPostProcessor to remove some beans? (How?)
Any help?

If I got your Question properly,
You can differ implementation by changing URL to particular Implementation name
Say Telecom is interface and AirtelImpl and RelianceImpl are Controllers then
Your request mapping
#RequestMapping(value= "/airtel/doBilling")
#RequestMapping(value= "/reliance/doBilling")
In this way, Implementation flow will differ.

I have followed these steps:
Created a custom annotation: #Devoted
Created a custom ImportBeanDefinitionRegistrar. Iterated already registered bean definitions to find out `#Devoted #Controller's and removed them.
Based on a request I will provide implementation details.

Related

inconsistent bean validation initialization of ConstraintValidator defined via ServiceLoader

This question asks for some specifics about more general topic regarding modularization of bean validation I asked before.
In question linked above, following this documentation and this post I split annotation and ConstraintValidator definition into 2 java modules, and linked them together using ServiceLoader as shown in documentation here. Works, mostly. But there is one unsolved issue, that it does not work for validation defined via XML, which I did according to documentation again. What does not work: The pairing between annotation and ConstraintValidator is not set, the service loader stuff is not used at all.
To recap: I have working setup using this ServiceLoader approach and it works when validating stuff coming through rest layer. All paired correctly.
BUT! We are getting these DTOs also through kafka. And here we have two different flows. There is some initialization of common ConstraintValidators on startup, and then:
if we first get REST message, ServiceLoader stuff is discovered only at this request time, some next initialization is done seemignly, and after that even kafka messages works, meaning pairing for custom validator is available everywhere. (Great!)
if kafka message arrives first though(typical), no service loader stuff is consulted and somehow it 'destroys' the configuration in way, that even if later rest request comes it won't work either, saying, that there is no ConstraintValidator for given annotation. The initialization is completed somehow defectively.
validation.xml is as easy as:
<validation-config
xmlns="http://xmlns.jcp.org/xml/ns/validation/configuration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/validation/configuration validation-configuration-2.0.xsd"
version="2.0">
<constraint-mapping>/META-INF/validation-constraints.xml</constraint-mapping>
</validation-config>
notes:
2.0 version is because of hibernate-validator 6.2.0 which comes from spring dependency management.
Why not use annotation and dump this xml stuff altogether? Not mine file, unmodifiable.
If there is some trivial newbie mistake, please advise. Maybe there is some way how to kick in service loader functionality into action in validation.xml file, I'm not aware of and cannot find anywhere.
EDITS/suggestions:
A: try to inject validator on startup to make sure it's loaded:
#Autowired
private Validator validator;
#EventListener(ApplicationReadyEvent.class)
public void logReady() {
System.out.println(validator.toString());
}
did print initialized validator, did not help though.

Restcontroller method naming convention spring boot

Are there conventions for naming methods in the Restful spring boot conrtoller layer ?
I am in dilemma choosing the two name - getSomeData vs fetchSomeData.
Is it OK to use HTTP Verbs (get,post,put) inside controller method names?
I think the most important thing is to be consistent in all your Controllers and to be explicit about what the method is supposed to be doing. It is completely ok to use HTTP verbs in the method names, especially in regards to GET. But when you have POSTs for example, that is usually a creation of a resource, so a method called createWhateverResource instead of postWhateverResource. The important thing is to be clear and let the name of the method be self-explanatory.
I checked a bit on the net. My conclusions:
There are no official naming rules
Official Spring Boot documentation uses short names: all(), one(), etc.
Names for the URLs are most important, method names are secondary
You never call these methods directly in code, they are only called by Spring framework.
A related note - for methods returning HTML (using Thymeleaf templates) I would probably call the methods by the page that they return: home(), orderDetails(), etc. Again for the same reason - we never call the methods directly. At the same time, it is very clear that #Controller and #RestController classes contain only methods returning HTTP responses to specific endpoints. Therefore, the verbs are probably not necessary.

Spring Boot - Where in code can I find this Bean. Is it a Bean?

Hi I'm looking at a Spring Boot application and I'm trying to understand everything that it does. It uses Camel and I am not finding the documentation for Camel especially helpful. Basically I might have a fundamental misunderstanding that a Camel SME would really be able to help with. The piece of code I am looking at is ...
public class SBJobScheduler extends RouteBuilder {
from("direct:alertBatch")
.log(LoggingLevel.INFO, SB_LOGGER, "#The Scheduler is going to start ::sbJob:: batch.# ")
.to("spring-batch:sbJob")
.end();
So I am trying to find how in the heck can I know where "alertBatch" is. I don't see any beans by this name, but maybe I'm missing it. I just want to know what is this value and I'm using the debugger and it doesn't tell me.
alertBatch is the name that uniquely identifies this endpoint. From Camel documentation:
The direct: component provides direct, synchronous invocation of any consumers when a producer sends a message exchange. This endpoint can be used to connect existing routes in the same camel context.
URI format
direct:someName[?options]
Where someName can be any string that uniquely identifies the endpoint.
You can read more about this component here
I suggest that you create a public constant in the same class that creates the route, this way, when you need to call this route, you just refer the created constant. This way you turn your code clean, more readable and allows the call hierarchy functionality from IDEs.

Using RequestScope without ServletModule

I was exploring #RequestScoped and was wondering if there's way to use it without installing ServletModule. I am using Guice 3.0 + Jersey 1.17 and probably don't want to use GuiceContainer & GuiceServletContextListener.
I want object creation(injections) per request depending on some user input in the Jersey request. Is it possible? What can be performance & security considerations of using GuiceContainer if I had to replace my existing ServletContextListener with that of Guice?
If there's a way of using RequestScope as per my needs, can you give me some references for the same?
It is possible to bind a custom Scope implementation to a predefined scoping annotation like #RequestScoped. It does mean that then you cannot use ServletModule, since you can't bind two different implementations to the same scoping annotation.
See the documentation on Custom Scopes for details. You will need to write code to determine what constitutes a "request" for purposes of scoping, and trigger entering and exiting the scope as necessary.
For example, in the normal Guice implementation, ServletScopes.RequestScope uses a ThreadLocal initialized in GuiceFilter to keep track of what the current request is.

Webapi DefaultHttpControllerSelector does not properly resolve my controller

I have an WebApi application that contains some controllers (they are registered using the extension method RegisterApiControllers). This application references another assembly that contains other controllers that I don't want to expose(I have checked that they are not registered in the container). It happens that both have an OrderController, and when I try to access the /api/Order url, I get an exception "Multiple types were found that match the controller named 'order'." and the stack trace shows that I was in DefaultHttpControllerSelector.
I have seen that AutofacControllerFactory used to exist and there was even a ConfigureWebApi that registered it, but it is not anymore present in the default branch.(you can see it here http://alexmg.com/post/2012/03/09/Autofac-ASPNET-Web-API-(Beta)-Integration.aspx)
It seems also that we can not filter the namespace of the route definition in WebApi (it is possible to MVC).
So any idea on how I can use only the Controller registered in my Autofac container and not use the DefaultHttpControllerSelector that seems to scan all referenced assemblies to discover controller?
Thanks
The problem is that registering the controller with autofac is not really related to the routing process. Only once the routing process has identified which controller to dispatch to will Autofac be called to resolve the type.
It looks like, from digging around in the source, that you would need to write a replacement IHttpControllerSelector in order to handle two controllers with the same name. (which really sucks BTW).
You might be able replace the DefaultHttpControllerTypeResolver with an instance that is passed a predicate that filters out the controllers from the assembly that you want to ignore. It's a bit of a kludgy solution but might work.
Actually, you might be able to replace the DefaultHttpControllerTypeResolver completely with one that is based on registrations in your Autofac container. It is a very simple interface, so as long as Autofac have a some kind of discovery mechanism, you should be golden.
public interface IHttpControllerTypeResolver
{
ICollection<Type> GetControllerTypes(IAssembliesResolver assembliesResolver);
}

Resources