I want to define injection so that only if the injected interface has EJB it will be injected. This is used as a plug-in to the main EJB. How to do this? Is there some annotation for this?
I can use #PostConstruct to manually "inject" the variable. But then I have to handle the dependencies by myself. How can I handle dependencies knowing that one of them is optional? How do I handle the order of deployment of different dependent modules.
Update:
I see that google has an inject annotation with optional parameter:
import com.google.inject.Inject;
#Inject(optional = true)
Update 2:
JBoss has something that may be what I'm looking for:
import org.jboss.annotation.IgnoreDependency;
#IgnoreDependency #EJB OtherBean otherBean;
The solution would be to use JNDI and not injection in this particular case. That way I have full control over the dependencies.
Related
I am using a spring boot 1.5.4 project where I need a clarification on testing package.
I am seeing Spring Boot comes with #MockBean which is part of org.springframework.boot.test.mock.mockito package.
My question is - Is it similar to Mockito external dependency and I can avoid using Mockito as external dependency as spring boot mock.* package has all features which Mockito has?
As already pointed in Greg's answer , mockito core is already included in spring-boot-starter-test so its already there in your project, no external dependency is needed.
Having said that - mockito's #Mock and Spring's #MockBean are a bit different in a way that #MockBean is basically a #Mock plus #Bean so it does what mockito annotation does plus it works with like a bean too i.e. it places instances in Spring's application context and all other spring bean related concepts come into picture too.
From documentation -
Annotation that can be used to add mocks to a Spring
ApplicationContext. Can be used as a class level annotation or on
fields in either #Configuration classes, or test classes that are
#RunWith the SpringRunner.
Mocks can be registered by type or by bean name. Any existing single
bean of the same type defined in the context will be replaced by the
mock, if no existing bean is defined a new one will be added.
When #MockBean is used on a field, as well as being registered in the
application context, the mock will also be injected into the field.
For non - Spring applications where DI & context are not there, you shoudl use #Mock and for Spring apps , you should use #MockBean.
If you look at the dependencies for spring-boot-starter-test, you'll see that it depends on the Mockito library so it is included for you.
Suppose I have classes, which were instantiated not by Spring. For example, they can be instantiated by deserializer or by JavaFX.
Can I code these classes in the same way I code Spring beans and inject properties into them later?
Actually, I would like a routine, which would scan class with reflection, find all #Autowired annotations in it and inject values from application context?
Will this happen, if I call applicationContext.getBeanFactory().registerSingleton("myName", myBean)? Note, that I would no limit myself with singletons.
If beans are not instantiated by Spring, then you cannot ask Spring to inject dependencies or advise them.
This is a common mistake I see Spring neophytes make. They call new to instantiate a bean with annotations and can't understand why their dependencies aren't injected.
Spring will handle all the beans you instantiate with the bean factory. You are on your own with all others created using new.
How to Configure Dependency Injection in a Library Project?
Let me illustrate this question with the following example.
Maven Library Project
ReservationAPI
com.example.reservation-api
This project contains a convenience class called ReservationApiClient which uses a RestTemplate (from the Spring Framework) for making HTTP calls.
Is it possible to make the RestTemplate field #Autowired in this library project instead of instantiating it myself?
Maven Executable Project
org.company.application
This project is a Spring Boot application and uses the above ReservationAPI as a dependency. This app will create a #Bean for the convenience class ReservationApiClient contained in that library and will then execute its public methods which in turn make HTTP requests.
What is a good strategy and/or best practices for the scenario described above?
You can do this if you include autowiring in your library project although that means it would always need to be used with a Spring application context to get the value unless you also have getter/setter methods to use as well. However, I don't think using RestTemplate as an autowired object makes sense since there is nothing specific about a RestTemplate and unless you name the beans there is only one bean definition for a class. All of the methods for the RestTemplate require the URI there anyhow. So in this case I would just use the bean for your ReservationApiClient in your application.
One other way to do it is if you want to include Spring dependencies in your library (which I guess you already are by using RestTemplate) you can declare your ReservationApiClient as a #Service or #Component and then use the #ComponentScan annotation in your main Spring Boot project to search that library for components to include in the bean registry.
Another option is to use a feature like Spring Boot's Autoconfigure to create factories that use third party libraries and configure them per properties in your application settings. The auto configuration documentation would be a good place to start with this. You can see the starter projects they have on GitHub and then the associated Autoconfigure classes they have associated with these.
Let me know if any of this does not make sense.
I have a 3-tier application: web-service, service-layer and domain-layer. The web service is present in a web application (WAR). The service-layer and domain-layer are two JAR projects. The dependencies are:
web-service --> service-layer --> domain-layer
In the service layer, the services are annotated with #Service. In the domain-layer, the DAOs are annotated with #Repository. The web service implementation class uses the services of the service-layer JAR, so it keeps one instance of each service which is automatically injected (#Autowired).
The dependencies are well defined in my POMs. When I deploy my WAR on Tomcat, I get the following exception:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [com.mycompany.project.services.MyService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:952)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:821)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:735)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(AutowiredAnnotationBeanPostProcessor.java:551)
... 37 more
I quote from one relevant part in the Spring docs:
The scanning of classpath packages requires the presence of
corresponding directory entries in the classpath. When you build JARs
with Ant, make sure that you do not activate the files-only switch of
the JAR task.
I've checked and the service-layer JAR is present in the WEB-INF/lib directory.
Any idea?
Thanks
EDIT: I have only one context file which is located in the web-service layer project (WAR) under src/main/webapp/WEB-INF. In this context, I've enabled classpath scanning as follows:
<context:component-scan base-package="com.mycompany.project" />
The package com.mycompany.project is the base package of my project, under which there are the web-service (com.mycompany.project.server), service-layer (com.mycompany.project.services) and domain-layer (com.mycompany.project.domain) packages.
I've solved the issue. I don't understand why what I've done was causing such an issue. Each service implements an interface that defines its public methods. In my web service implementation class, the references to the services used the implementation classes and not the interfaces. I just changed them to use the interface, and I don't get the issue anymore. Could anyone explain me what's wrong with using the services implementation classes instead of the interfaces for the autowiring?
This is an answer for your EDIT:
The reason why referring to the interface worked but the concrete implementation failed is probably to do with the dynamic proxies that Spring creates for cases where you have your services annotated with #Transactional etc. What happens in such cases is that the type of your beans are not the implementation type anymore, but wrap around your impementation type. So when you have #Autowired by implementation type, it just cannot find it by type (which is the default).
Your fix is very appropriate, as a dynamic proxy continues to derive from the interfaces that you have defined for your implementation and so can inject by interface type - the reference that I have provided does a better job explaining this.
make sure you used <context:component-scan base-package="your.service.package"/>
check your autowired strategy is byName or byType; if byName, the Service annotation's name value should be right.
if problem still exist, check spring's log, it will print all found components' name, you could know the service is founded or not.
Can you show your component scanning configuration? If this is not set up correctly then Spring may not be discovering your service.
You want something like:
<context:component-scan base-package="your.service.package"/>
Edit:
I think the problem is that your #Service annotation is on the interface rather than implementation class.
If you annotate your service implementation then your web controller can use either:
#Autowired
private ExampleService service;
or
#Autowired
private ExampleServiceImpl service;
I've noticed recently that spring can wire up my ejb's for me if I annotate the ejb with #Interceptors(SpringBeanAutowiringInterceptor.class). I've never actually done this so don't know the details.
I was wondering, is there a way to get this to work with other kinds of beans, for example, #WebService annotated ones as well.
At the moment in my web service classes (because the application server manages them) I have to load the dependencies from the BeanFactory and would thus prefer to have them autowired.
I know I could use the #Configurable annotation but am not particularly keen to have to specify and agent on the VM.
Is this possible?
Once again, spring has thought of this use case and catered for it!
The problem is that #WebService is not a spring annotation, it is a JAX-WS annotation and thus classes that are annotated with #WebService to be exposed as web services are not managed by spring, but their life cycle is managed by JAX-WS.
The way to handle this case is to have the JAX-WS managed bean extend org.springframework.web.context.support.SpringBeanAutowiringSupport - this will enable the #Autowire annotation, for example, to work in this bean. see here for more information
Yes, of course. There's #WebService, #Repository, #Controller, #Service, #Endpoint, and other annotations in Spring. Here's an example.