OSGI Component with unsatisfied references of satisfied services - java

I'm using OSGI with equinox, and having a problem on a new component dependency. It has two services references, which are both marked as 'Unsatisfied'.
This would be a simple unsatisfied references problem, it it weren't for the fact there is another component which uses one of this references and it's satisfied, the the other is a component which is satisfied on the system as well.
I've tried to debug the 'AgentServiceImpl' class to identify if this could be a problem on it's activation, but since it's references are unsatisfied the methods of the class aren't even called.
No clue of what I'm doing wrong on this case, any suggestion of fixes or ways to tackle this problem would be much appreciated.
[update]
I've noticed the Service I depend has this configuration on it's component declaration:
policy = ConfigurationPolicy.REQUIRE, configurationPid = "com.rm.ums.ruleengine"
So, if i don't define this, it should not build the component. However, even retrieving the ConfigurationAdmin and setting this configuration the component still won't go up. And there is no error message on the console for this, shouldn't it display an error or a warning in this case, so the developer know this is happening and can handle it?

It turns out this was a service configuration problem.
This component I was trying to inject had it's policy as 'REQUIRE', which means it won't start unless you provide it's configuration. I was providing the configuration on another bundle using the ConfigurationAdmin, but this configuration was being bonded to my bundle instead of the one which needs it.
Once I configured not to bind the configuration to my bundle (or unbind it manually), the service started as expected.
Probably this could be avoided case there was a warn message on the log stating this happened :(

Related

Can Spring circular reference errors happen randomly due to race conditions?

We have some builds that are failing with variations of this error:
Error creating bean with name 'cartServiceImpl': Unsatisfied dependency expressed through field 'addressServiceClient'; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'addressServiceClient': Bean with name 'addressServiceClient' has been injected into other beans [addressInfoServiceImpl] in its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.
The thing is, we never see this error when we start up the service on our desktops. We only see this error when the build runs on the CI server. In fact, most of the time when we're building the same code, this error does not occur. I have a test case where it runs four concurrent builds of the same branch and commit (targeting for deployment to four different clusters), and sometimes all four succeed, but sometimes one (or even two) of them will fail with this error.
My first theory, when I determined the seeming randomness of this, was that there was some screwy problem with our docker registry or docker cache, which was somehow occasionally giving us an older image (there was a related problem of this nature, for real, several weeks ago). Despite my desire to hang this on another team, I have to assume that there's something we're doing that could be causing this, but perhaps it's random because this is depending on a race condition. I find it hard to believe that Spring bean resolution could have race conditions.
Is there any possibility that an error like this might occur or not occur, depending on race conditions?
We're using Spring Framework 5.0.9 with Spring Boot 2.0.5.
Update:
Note that I still can't repeat this problem with ordinary testing on my laptop, but we were able to extract the jar file constructed on the CI server and download it to my laptop, and then run that directly, and it does get the same error. We compared the contents of the jar file between that jar and a "good" one, and the differences were subtle, no obvious problems that might cause this. We did notice that the AddressServiceClient mentioned in the error is second in the list of classes in the "bad" jar, and far down the list in the "good" jar.
I then thought that perhaps adding #Lazy to the AddressServiceClient class would avoid the problem (not that I don't say "fix"). I tried modifying that "bad" jar file locally, using "zip" to update the jar file with the updated class file, and I found that that resulting jar file did NOT demonstrate the symptom. However, when I finally merged the PR with this change and the builds ran on the CI server, one of them still failed with the same error.
You can use setter injection, it use Spring L3 Cache.
For example:
private TmsOrderService tmsOrderService;
#Autowired
public void setTmsOrderService(TmsOrderService tmsOrderService) {
this.tmsOrderService = tmsOrderService;
}
Spring L3 Cache avoid circular dependencies.

Do action before spring context created

How can I execute the action, before Spring context created? I found only one solution that more or less can satisfy me, it is listening ApplicationStartingEvent but I don't know how correctly do it because Spring doesn't see listener bean because context not created yet. So maybe someone knows ways how to catch ApplicationStartingEvent or maybe another better solution to do it.
Interface ApplicationContextInitializer could suffice for your requirement.
Read ApplicationContextInitializer documentation
Implementing ApplicationContextInitializer allows you to do additional tasks/initializations before persistent bean definition is loaded (i.e. your application-context.xml). One such use is, when you want to select profiles before you will load definitions.

Spring Boot App - Could not resolve placeholder

I have a Spring Boot app which imports an external library. I am reading the spring.xml in the dependency that I have imported. It is throwing an error because it is looking for "propDir" which I have not defined. I see an error "Invalid bean definition with name .... Could not resolve placeholder 'propDir'"
<value>file:${propDir}/env-config.properties</value>
I have seen another spring boot app import the same dependency and it starts just fine. When I debugged the start sequence and saw the value of propDir , I saw that it was not substituted and I see "file:${propDir}/env-config.properties" in the created bean.
I have searched the app , but haven't really figured out how the other app is not throwing the error. Is there a piece of config that I am missing?
You need to specify a value for propDir.
This can be done either by jvm argument like
-DpropDir=nameoffoldertouse
or via a properties file loaded via a PropertyPlaceholderConfigurer.
Other applications that rely on this bean may have a default hidden away.
It is likely that the bean relying on this value will need it to guarantee its correct behaviour, if you do not want to provide this property do not rely on the bean that uses it.
Properties to a spring boot application can be passed using different ways, very likely for the other application the property for "propDir" is I believe getting passed as one of the ways specified in this documentation: http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html

Custom exception mapping for bean validation on TomEE 7?

Context
We use a javax.ws.rs.ext.ExceptionMapper<Exception> annotated as #javax.ws.rs.ext.Provider to handle all exceptions. Internally this ExceptionMapper is distinguishing between different types of exceptions to determine what information to reveal to the client.
In the case of the javax.validation.ConstraintViolationException, we return additional information about which field was invalid and why.
Problem
We just switched from TomEE 1.7.2 JAX-RS to TomEE 7.0.0-SNAPSHOT webprofile.
With TomEE 1.7.2 JAX-RS we used the openejb.jaxrs.providers.auto=true system property, our ExceptionMapper was automatically found and used.
With TomEE 7.0.0-SNAPSHOT webprofile the property is no longer necessary to benefit from auto discovery.
However the org.apache.cxf.jaxrs.validation.ValidationExceptionMapper is also discovered and now acts as the preferred ExceptionMapper for the javax.validation.ConstraintViolationException. Our own ExceptionMapper does not run, and the client therefore gets no information about what went wrong during validation.
Our own ExceptionMapper<Exception> still handles all other exceptions.
What I already tried
"duplicate" the specialized ExceptionMapper
I placed my own javax.ws.rs.ext.ExceptionMapper<javax.validation.ConstraintViolationException> next to my resources, hoping that it takes precedence over the CXF one.
Still the org.apache.cxf.jaxrs.validation.ValidationExceptionMapper takes precedence.
Update: it turned out that this indeed does the trick. I don't know why my initial test didn't work.
Disable the ValidationExceptionMapper via system.properties
In the changelog of TomEE 7.0.0-SNAPSHOT I noticed
TOMEE-1336 Support classname.activated = true/false for auto discovered providers
Looking at the corresponding changeset I was hopeful that I could just disable the org.apache.cxf.jaxrs.validation.ValidationExceptionMapper by adding
org.apache.cxf.jaxrs.validation.ValidationExceptionMapper.activated=false
to our system.properties.
This remained without effect.
Questions
Is this CXF or TomEE behaviour?
How do we configure which ExceptionMapper takes precedence?
Makes some time now but think it is needed by spec but you can disable it by setting cxf.jaxrs.skip-provider-scanning=true.
It completely disables auto providers including the scanned ones but then you can control the one you want in openejb-jar.xml - surely the best and safer solution IMHO cause otherwise you depend a lot of the libs and container setup you use.
There is no priority afaik cause the exception hierarchy is used.
edit: missed a part: you need to impl ExceptionMapper{ValidationException} otherwise CXF one has higher priority than your own one (Exception is less specific)
edit 2: https://issues.apache.org/jira/browse/TOMEE-1656 for the activated support

Spring Integration Test: Incompatible Beans with the Same Name and Class

I'm working on resolving an odd issue I'm having with my project that has cropped up since we've started working on integration testing. What happens is that I use the "jetty-maven-plugin" to startup an instance of the application, once it's started the "maven-failsafe-plugin" starts to run the integration tests. This much is setup and running well.
What I'm trying to do now is this: I'd like to get a handle on my service layer so that I can setup some fixtures for my tests to run against. Up until now, our integration tests have been pretty simple minded and I'd like to turn it up a notch and test the actual filling out of forms and so on. For this to work, I need to be able to setup some fixtures and then remove them so that these test are reproducible. We're running against a test database that we use for just this purpose.
From what I've read, this is not unreasonable. Nonetheless, when I actually run the tests I get a very odd error message and stack trace. From what I can tell, Maven starts up the application in Jetty without issue. Then the failsafe plugin starts running the test and, once it hits the first integration test, it begins instantiating a Spring instance and context. It correctly pulls in it's properties and configuration files but when it tries to actually inject the service object, I am seeing this error:
Caused by: org.springframework.beans.factory.BeanDefinitionSt
oreException: Unexpected exception parsing XML document from class
path resource [app-config.xml]; nested exception is
org.springframework.context.annotation.Conflicting
BeanDefinitionException: Annotation-specified bean name
'pesticideRoleRepositoryImpl' for bean class
[dao.role.PesticideRoleRepositoryImpl] conflicts with existing,
non-compatible bean definition of same name and class
[dao.role.PesticideRoleRepositoryImpl]
I will spare you all the stack trace, I can make it available at any time. ;-)
I started wondering if I was going about this all wrong and so I went back and setup a test project in much the same way. The test project is far simpler and doesn't have this issue. When it runs the integration tests the service objects are injected without issue. If you are interested, you can take a look at my test project on GitHub.
My Question Is This...
Has anyone seen this error before? Could there be some conditions under which Spring will have this kind of problem?
It's clear to me that with this kind of integration testing, I end up with two Spring containers that use the exact same configuration. I thought this might be the problem but the test project works the same way and doesn't have this issue. I'm also troubled by the fact that even though there are two beans with the same name and class, Spring believes that they are incompatible.
Thank you, any help would be greatly appreciated! :-D
This error occurs when two diferent files contains the same class (bean) definition and are incompatibles, ie oldBeanDefintion.equals(newBeanDefinition) == false
You could check:
Why the scanner is loading this class twice.
Why oldBeanDefintion.getSource().equals(newBeanDefinition.getSource()) = false
Why oldBeanDefinition.equals(newBeanDefinition) = false
You could put a break point on ClassPathBeanDefinitionScanner.isCompatible() or extends ClassPathBeanDefinitionScanner and override isCompatible method and log some useful info to find the error.
As last option, XML BeanDefinitions cannot be overriden by scanned ones, so if you define the bean in XML, scanned clases with same bean name will be ignored.
The selected answer was correct, the root problem was that there were multiple instances of the bean being created. Interesting, though, is that the other instances were mock instances; they were being picked up because they were mixed in with the tests and all of the tests were placed in the classpath.
There are likely many solutions, my fix was to add a "context:exclude-filter" to the "context:component-scan" declaration in my application configuration.

Categories

Resources