Play! Framework - Spring.getBeanOfType works but #Autowired fails - spring

I am using play spring-1.0.1 module and as per the documentation :
To enable component scanning, add this line to the
/conf/application.conf file:
play.spring.component-scan=true
Note that enabling this scans for #org.springframework.stereotype.Component,
#org.springframework.stereotype.Repository,
#org.springframework.stereotype.Service
to identify Spring beans.
Additionally, running the component
scan enables support for annotation
based configuration (i.e.,
#org.springframework.beans.factory.annotation.Autowired,
etc).
When I try the same thing, it fails saying NullPointerException, since it is not able to wireup the beans to the corresponding class.
Although
play.modules.spring.Spring.getBeanOfType(UserManager.class);
just works fine on my models.
Is it a known issue or I am doing it incorrectly
Thank you

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.

In Spring Boot how do you register custom converters that are available when parsing application configuration?

In a Spring Boot application how do you register custom converts to be used when processing application configuration?
I have made a custom convert (org.springframework.core.convert.converter.Converter) so it can be used by the ApplicationConversionService/Binder to parse #ConfiguraitonProperties defined in application.properties and application.yaml configuration files but do not know how to register it.
I have tried the solution here https://stackoverflow.com/a/41205653/45708 but it creates an instance of my converter after the application configuration parameters have been processed.
I ran into this issue myself recently. From what I can tell, the key issue is that binding to configuration properties occurs very early in the Spring startup process, before the Application Context is fully initialized. Therefore the usual methods for registering a converter are not reliable. In fact the ConversionService used for configuration binding appear to be a one-off and not really connected to the ConversionService that is stored in the Application Context.
I was able to get something working but it feels like a hack, as it relies on internal implementation details that may work today but not tomorrow. In any case, this is the code I used:
((ApplicationConversionService) ApplicationConversionService.getSharedInstance()).addConverter(myCustomConverter);
The trick I found was to make sure this gets called as soon as possible at application startup so that it gets called before the configuration binding where it's needed. I put it in a #PostConstruct block inside my main #SpringBootApplication class as this seemed to get invoked early on, at least in my case.

Can't find #SpringBootApplication from JUnit test file

I was following the guide here, https://spring.io/guides/gs/spring-boot/ - cloned the project, built with Gradle and tried to run...application ran fine. Then I changed some file structure as per my requirement and tried to run the unit test case given there, but getting this error -
Unable to find a #SpringBootConfiguration, you need to use #ContextConfiguration or #SpringBootTest(classes=...) with your test
I only restructure the codes in there, and this is my current project structure -
/projectroot
- /src/main/java
-Application.java
-/controller
-MyController.java
-/util
-MyUtil.java
-/model
-MyModel.java
Now trying to run test case from
/src/test/java/controller/MyControllerTest.java
I have gone through this Stack Overflow link and understood that if I put my test folder under /src/main/java/ it may work. But if I do that test file doesn't compile and it also doesn't seem the right way to put application code along with test code. I know I'm missing something very fundamental.
The way you setup your test (using the whole spring boot context), I believe MyControllerTest.java needs to be at most at the same level as Application.java. Also, I notice Application.java is using default package, you should move it into a package, so that all your beans are below your Spring Boot main class:
/projectroot
- /src/main/java/com/example/project/
-Application.java
-/controller
-MyController.java
-/util
-MyUtil.java
-/model
-MyModel.java
- /src/test/java/com/example/project/
-MyControllerTest.java
Spring's documentation
How Spring Boot's context is resolved from a test:
The search algorithm works up from the package that contains the test
until it finds a #SpringBootApplication or #SpringBootConfiguration
annotated class. As long as you’ve structure your code in a sensible
way your main configuration is usually found.
About using the default package with Spring Boot:
When a class doesn’t include a package declaration it is considered to
be in the “default package”. The use of the “default package” is
generally discouraged, and should be avoided. It can cause particular
problems for Spring Boot applications that use #ComponentScan,
#EntityScan or #SpringBootApplication annotations, since every class
from every jar, will be read.
We recommend that you follow Java’s recommended package naming conventions and use a reversed domain name (for example, com.example.project).

Spring overwriting controller

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.

Unable to veto a stage-specific #Specializes class in Websphere 8.0

In my first foray into the world of JSF and CDI, I've been trying to use the #Specializes annotation to override behaviour in a managed bean in unit tests only. We have the MyFaces CODI jars in the WEB-INF/lib, and the unit test aspect works just fine, i.e. my Mock specialization is picked up and used:
#ProjectStageActivated(ProjectStage.UnitTest.class)
#Specializes
class MockCustomerSearchScreenBean extends CustomerSearchScreenBean {
...
That works fine when the project stage really is unittest, but when it's anything else, the WAR startup fails with
org.apache.webbeans.exception.WebBeansDeploymentException: org.apache.webbeans.exception.inject.InconsistentSpecializationException: Specialized bean for class : class bla.bla.MockCustomerSearchScreenBean is not enabled in the deployment.
at org.apache.webbeans.config.BeansDeployer.checkSpecializations(BeansDeployer.java:653)
I know the #Observes ProcessAnnotatedType is firing during bean discovery because I can see the veto flag has been set on the ProcessAnnotatedType by the CODI ActivationExtension, and I also wrote my own extension which explicitly vetos the Mock version, but the container is still determined to try and use the specialized version and not the 'normal' one. I also tried wrapped the AnnotatedType to not advertise the #Specialization annotation.
There's no simple way for me to not deploy the mock subclass to my desktop server either.
Is there any way to persuade WebSphere's version of open web beans to ignore the Specialization based on project stage (or some other factor I can control)?
WAS 8.0 uses a quite old version of OpenWebBeans. This issue was fixed long ago in OpenWebBeans. I would move to 8.5+. And/or try the same with #Alternative (but with BDA switched off).

Resources