I'm trying to replace a default implementation provided by DeltaSpike (LocaleResolver) with my own implementation via #Alternative.
#Alternative
#RequestScoped
public class ExampleLocaleResolver implements LocaleResolver {
}
<alternatives>
<class>org.example.app.ExampleLocaleResolver</class>
</alternatives>
It seems the only way to make ExampleLocaleResolver the selected bean is by using #Priority or #Specializes.
For example, the following two works perfectly fine:
#Priority(1)
#Alternative
#RequestScoped
public class MyLocaleResolver implements LocaleResolver {
}
#Specializes
#RequestScoped
public class MyLocaleResolver extends DefaultLocaleResolver {
}
My understanding is that with CDI 1.1+, it should be possible to override beans from libraries with alternatives without any kind of hacks.
Could someone please help me understand why I'm unable to inject the #Alternative bean without the #Priorty annotation?
(Warning: I'm weak in the #Alternative area, but I think I understand this and can answer it accurately.)
I think the problem is that without using #Priority you are restricted to making assertions about bean archives, and your bean archive is not the same as the bean archive from which the DeltaSpike LocaleResolver is sourced. My understanding is in CDI 1.1+ the only way to cause application-wide #Alternative selection to happen is with the #Priority annotation.
Related
I am getting the following error in a Spring Boot project on which I work:
The bean 'auditLogDao' could not be injected as a '{redactedpathwithcorporatename}.AuditLogDao' because it is a JDK dynamic proxy that implements:
org.springframework.data.jpa.repository.JpaRepository
Action:
Consider injecting the bean as one of its interfaces or forcing the use of CGLib-based proxies by setting proxyTargetClass=true on #EnableAsync and/or #EnableCaching.
I have tried a variety of solutions on StackOverflow without success, specifically:
Checking that I am indeed calling the interface, not the implementation.
Adding #Component to the top of SwitchUserFilter
Changing #Resource to #Autowired.
AuditLogDao.java
public interface AuditLogDao extends JpaRepository<AuditLog, String> {}
AuditLogService.java
public interface AuditLogService {
AuditLog save(final AuditLog auditLog);
}
AuditLogServiceImplementation.java
public class AuditLogServiceImplementation implements AuditLogService{
#Resource private AuditLogDao auditLogDao;
#Override
public AuditLog save(AuditLog auditLog) {
return auditLogDao.save(auditLog);
}
}
The file where I actually want to use the service to save information
SwitchuserFilter.java
public class SwitchUserFilter
extends org.springframework.security.web.authentication.switchuser.SwitchUserFilter {
#Resource AuditLogService logService;
'''
logService.save(auditLog);
'''
}
I am relatively new to Spring Boot, so an explanation of why it fixes the problem would be appreciated.
I believe the following code will solve your problem. Add it to the AuditLogServiceImplementation and remove the #Resource annotation from the auditLogDao.
#Autowired
private ListableBeanFactory beanFactory;
#EventListener({ContextRefreshedEvent.class})
void contextRefreshedEvent() {
auditLogDao = beanFactory.getBean(AuditLogDao.class);
}
You can do a similar trick in the filter too, whatever more comfortable for you.
I don't know what is the exact problem, but it's some kind of circular-dependency-like issue.
So by manually importing any bean which is affected in this loop, you can resolve the loop. You will set this one particular dependency AFTER Spring had created all of the other beans.
In my ApplicationContext I have several Beans being created the same style. So I have a lot of dublicated code writing a FactoryBean for each of this beans. Those beans have a common ground, implementing all one special interface.
I would like to move all that bean creation to one factory. That one would have to provide a methode like this
<T extends CommonInterface> T createInstance(Class<T> clazz);
There I could implement all the instantiation necessary to create one of my special beans.
My implementation would be called by spring for
#Autowired
private MyCommonInterfaceImplementation impl;
in that way
createInstance(MyCommonInterfaceImplementation.class)
So far I looked at BeanFactory and FactoryBean, both seem not to be I'm searching for.
Any suggestions?
why not use #bean
#Bean
public MyCommonInterfaceImplementation getMyCommonInterfaceImplementation(){
return MyBeanFactory.createInstance(MyCommonInterfaceImplementation.class);
}
//should autowire here
#Autowired
private MyCommonInterfaceImplementation impl;
Basically you need the #Bean annotation on a "factory" only if you need some special handling during the creation of a bean.
If everything can be #Autowired, either by setters, fields, or one constructor, and nothing else needs to be done on a bean during initialization, you can simply declare the annotation #Component on each implementation of your interface. This works as long as you have component scanning active inside your application. The result will be that for each component spring will create a bean which you can use.
I'm writing this on a mobile so showing code is not the best. Just follow some tutorial on #ComponentScan, or if you need, let me know and I can augment this answer with an example.
As of Spring 4.3 you no longer have to annotate your bean classes and you can let them be instantiated via a componentscan.
#Configuration
#ComponentScan(
value = "some.package.path",
includeFilters = {
#Filter(type = ASSIGNABLE_TYPE, value = {
MyClass1.class,
MyClass2.class,
MyClass3.class
})
})
This actually creates beans for the three classes listed there. The example should work without filters as well (everything in the package becomes a bean). This works as long as the classes have a single constructor that can be used for autowiring. I don't think it is possible to filter for all implementations of a particular interface and then register a bean.
To do that, you might do something with a ContextListener and e.g. use reflection to find out what classes to instantiate and then use context.autowire(..) to inject any dependencies from your context. A bit hacky but it might work.
#Override
public void onApplicationEvent(ContextRefreshedEvent event) {
ApplicationContext context = event.getApplicationContext();
MyClass bean
= context
.getAutowireCapableBeanFactory()
.autowire(MyClass.class, Autowire.BY_NAME.value(), true);
...
}
That still leaves the problem of how to get the bean registered in the context of course.
You might also be able to adapt the answer to this SO question on how to add beans programmatically.
Finally the best approach I've found is using a ConfigurationClassPostProcessor. As example I've used https://github.com/rinoto/spring-auto-mock
But, since it is quite complicated and "too much magic" to create beans from nothing, we decided to explicitly create those beans via #Bean.
Thanks for your answers.
I tried the following code with Spring 3.x which failed with BeanNotFoundException and it should according to the answers of a question which I asked before - Can I inject same class using Spring?
#Service
public class UserService implements Service{
#Autowired
private Service self;
}
Since I was trying this with Java 6, I found the following code works fine:
#Service(value = "someService")
public class UserService implements Service{
#Resource(name = "someService")
private Service self;
}
but I don't understand how it resolves the cyclic dependency.
EDIT:
Here's the error message. The OP mentioned it in a comment on one of the answers:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [com.spring.service.Service] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
Update: February 2016
Self autowiring will be officially supported in Spring Framework 4.3. The implementation can be seen in this GitHub commit.
The definitive reason that you cannot autowire yourself is that the implementation of Spring's DefaultListableBeanFactory.findAutowireCandidates(String, Class, DependencyDescriptor) method explicitly excludes the possibility. This is visible in the following code excerpt from this method:
for (String candidateName : candidateNames) {
if (!candidateName.equals(beanName) && isAutowireCandidate(candidateName, descriptor)) {
result.put(candidateName, getBean(candidateName));
}
}
FYI: the name of the bean (i.e., the bean that's trying to autowire itself) is beanName. That bean is in fact an autowire candidate, but the above if-condition returns false (since candidateName in fact equals the beanName). Thus you simply cannot autowire a bean with itself (at least not as of Spring 3.1 M1).
Now as for whether or not this is intended behavior semantically speaking, that's another question. ;)
I'll ask Juergen and see what he has to say.
Regards,
Sam (Core Spring Committer)
p.s. I've opened a Spring JIRA issue to consider supporting self-autowiring by type using #Autowired. Feel free to watch or vote for this issue here: https://jira.springsource.org/browse/SPR-8450
This code works too:
#Service
public class UserService implements Service {
#Autowired
private ApplicationContext applicationContext;
private Service self;
#PostConstruct
private void init() {
self = applicationContext.getBean(UserService.class);
}
}
I don't know why, but it seems that Spring can get the bean from ApplicationContext if is created, but not initialized. #Autowired works before initialization and it cannot find the same bean. So, #Resource maybe works after #Autowired and before #PostConstruct.
But I don't know, just speculating. Anyway, good question.
By the way, the more elegant solution to the self-invocation problem is to use AspectJ Load-Time Weaving for your transactional proxies (or whatever AOP-introduced proxy you're using).
For example, with annotation-driven transaction management, you can use the "aspectj" mode as follows:
<tx:annotation-driven mode="aspectj" />
Note that the default mode is "proxy" (i.e., JDK dynamic proxies).
Regards,
Sam
Given above code I don't see a cyclic dependency.
You injecting some instance of Service into UserService.
The implementation of the injected Service does not necessarily need to be another UserService so there is no cyclic dependency.
I do not see why you would inject a UserService into UserService but I'm hoping this is a theoretic try out or such.
Get AOP proxy from the object itself question suggests alternative hacky approach with AopContext.currentProxy() that may be suitable for special cases.
Just another aproach:
#EnableAsync
#SpringBootApplication
public class Application {
#Autowired
private AccountStatusService accountStatusService;
#PostConstruct
private void init() {
accountStatusService.setSelf(accountStatusService);
}
}
#Service
public class AccountStatusService {
private AccountStatusService self;
public void setSelf(AccountStatusService self) {
this.self = self;
}
}
with this your service will be in proxy. I did this to work with async methods inside itself.
I have tryied #sinuhepop solution:
#PostConstruct
private void init() {
self = applicationContext.getBean(UserService.class);
}
It did a injection but the service wasn't inside proxy and my methods wasn't running on a new thread. With that aproach it works as i would like.
It looks like spring creates and configures an object and then places it in the bean look up context. But, in the case of Java, I think it creates the object and ties it to the name and the during configuration when the object is looked up by the name it is found in the context.
This is my solution for small to medium sized projects. No AspectJ or application context magic, it works with singletons and constructor injection and is very easy to test.
#Service
#Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
class PersonDao {
private final PersonDao _personDao;
#Autowired
public PersonDao(PersonDao personDao) {
_personDao = personDao;
}
}
I've moved my code from Spring's XML configuration to Java Configuration. I have everything working, but I have a question about how I implemented prototype beans - mainly, while what I'm doing works, is it the best way to do this? Somehow it just feels off!
I wrote the bean class this way:
#Component
#Scope("prototype")
public class ProtoBean {
...
}
Then to use the bean - this is the part that I'm just not sure about, although it does work:
#Component
public class BeanUser implements ApplicationContextAware {
ApplicationContext context;
#Override
public void setApplicationContext(ApplicationContext context)throws BeansException
{
this.context = context;
}
public void getProtoBean() {
ProtoBean protoBean = context.getBean(ProtoBean.class);
}
}
This gets me a prototyped bean, and in unit tests I just mocked the context, called setApplicationContext with the mock, and had the getBean call of the mock return a mock ProtoBean. So all is well.
I did this in the XML by using a factory, but that didn't seem to work too well, so this is where I ended up. But is there a way to do this without the context? Or just a better way?
Thanks!
I don't think is so much an issue of Spring XML vs Java-base configuration, but one of matching dependency scopes. Since Spring can only do dependency injection on the singleton-scoped bean at creation time, you have to lookup the prototype-scoped bean on demand. Of course the current bean-lookup approach works, but creates a dependency on the ApplicationContext. I can suggest a few other possibilities but the root of the issue is really what is involved in producing a ProtoBean, and what trade-offs should you accept.
You could make BeanUser itself prototype-scoped, which would allow you to wire in the ProtoBean as a member. Of course the trade-off is you now have the same problem on the clients of BeanUser, but sometimes that would not be a problem.
Another path could be using something like a singleton-scoped ProtoBeanFactory to provide ProtoBean instances, and hiding dependency lookups within the ProtoBeanFactory.
Finally, you could use a scoped-proxy bean to effectively hide the factory. It uses AOP to do this, and isn't always clear to others what sort of voodoo you have going. With XML you'd use <aop:scoped-proxy/> on the bean declaration. For annotations you'd use:
#Scope(proxyMode = ScopedProxyMode.TARGET_CLASS, value = "prototype")
I have several #Stateful SessionBeans annotated like this:
#Stateful
#Remote(AdminFacade.class)
public class TAdminFacadeBean implements TgAdminFacade,Serializable
{
...
}
Now I want to test them with Arquillian (1.0.0.Alpha5), but get lot's of different errors, messages vary either if the annotations are #Stateful or #Stateless, if a #Named is added or if there is no #Remote (and implements Interface).
Steps to reproduce:
Create new maven project with
archetype org.jboss.weld.archetypes:jboss-javaee6-webapp:1.0.1.CR2
You might need to set jboss.home (see
readme.txt)
Modify pom.xml and set profiles.profile[id=default].build.plugins.plugin[artifactId=maven-surefire-plugin].configuration.skip
to false
Start JBoss-6.0.0.Final
Execute test (should pass): mvn test -Parq-jbossas-remote
The bean tested here ist MemberRegistration:
#Model
public class MemberRegistration
{
...
}
If you now change #Model to #Stateful, JBoss loops with stacktraces, with #Named #Stateful this error:
java.lang.IllegalArgumentException: ArquillianServletRunner not found.
Could not determine ContextRoot from ProtocolMetadata, please contact
DeployableContainer developer.
#Named #Stateless:
javax.transaction.NotSupportedException: BaseTransaction.checkTransactionState
- ARJUNA-16051 thread is already associated with a transaction!
How can I test my #Stateful Beans with Arquillian?
Over and over again working in this issue I figured out the solution. Even I hate answering my own question I hope this can help somebody in the future.
The annotation for the #Stateful session bean (at the top of the question) are correct and stay the same. In the Arquillian test case the bean was originally injected with
#Inject MemberRegistration memberRegistration;
This works with #Model beans but not with #Stateful session beans and a #Remote interface. It seems this kind of beans must be injected with
#EJB private AdminFacade adminBean;
See What is the difference between #Inject and #EJB