I am trying to understand CDI. I have an interface:
public interface Person {
public String getName();
}
And a class that implements Person:
public class Male implements Person {
public Male() {}
#Override
public String getName() {
return "ra";
}
}
In the main class, I tried:
public class Main {
#Inject
private Person person;
public static void main(String... args) {
System.out.println(new Main().person.getName());
}
}
but the above code throws NPE on person.getName(). I created the project using maven and the scope of javaee api is compile. What am I doing wrong?
You miss to start a CDI container it seems.
Note that any annotation on a class is just like a post-it. It is really only an additional info and not real code. This information has to be interpreted. This is what the CDI container does.
I've written up an introduction article to CDI which explains a little bit of the basics:
https://jaxenter.com/tutorial-introduction-to-cdi-contexts-and-dependency-injection-for-java-ee-jsr-299-104536.html
What do you miss:
1.) add an empty META-INF/beans.xml file. Or add a scope annotation like #ApplicationScopedto your Male.java class.
2.) add a CDI container. There are multiple options. If you want to use the Apache OpenWebBeans CDI container then you can find some infos here https://openwebbeans.apache.org/owbsetup_se.html
You can also find a working sample over here
https://github.com/apache/openwebbeans/tree/trunk/samples/standalone-sample/pom.xml
https://github.com/apache/openwebbeans/blob/trunk/samples/standalone-sample/src/main/java/org/apache/webbeans/se/sample/Boot.java#L68
Related
Hi i have a rather specific question regarding Spring Aspects that leaves me puzzled. I played around with Springs and Apsects and and tried out a very simple Example to see how it works:
#Component
public class Comment {
private String text;
private String author;
public String get() {
return text;
}
public void setText(String text) {
this.text = text;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
}
#Aspect
public class LoggingAspect {
#Around("execution(* aop.beans.*.*(..))")
public void log(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("Start Aspect for method: " + joinPoint.getSignature());
joinPoint.proceed();
}
}
My configuration file:
#Configuration
#ComponentScan("aop.beans")
#EnableAspectJAutoProxy
public class ProjectConfig {
#Bean
public LoggingAspect aspect() {
return new LoggingAspect();
}
}
With that i used a simple Main method to play around with the concept a little:
public class Main {
public static void main(String[] args) {
#SuppressWarnings("resource")
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ProjectConfig.class);
context.registerShutdownHook();
CommentService service = context.getBean(CommentService.class);
Comment comment = context.getBean(Comment.class);
comment.setAuthor("Andreas");
comment.setText("Hallo.");
service.publishComment(comment);
System.out.println(service.getClass());
}
}
This worked fine but something strange happens when ich change the hirarchy of the comment class. I wanted to see what happens if the class implements a generic interface so i changed it as follows
public class Comment implements Supplier<String>
I immediately get an error with the following stack trace:
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'aop.beans.Comment' available
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:351)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:342)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1172)
at aop.Main.main(Main.java:17)
This left me wondering why that is? If i remove the generic superinterface or the aspect bean everthing works fine but both things together do not seem to fare well. Can someone provide an explanation? Is Spring not able to create a Proxy object if the class has a generic superclass?
Edit: The solution is in the comments :) i found further documentation on the mechanism in Spring Proxy Mechanism Documentation
This happens because of the way Spring implements AOP.
When proxied class (Comment in your case) doesn't implement any interfaces, CGLib proxy is used. Basically, it generates a class which is subclass of proxied class. Thus, you can getBean by parent's class.
When there are implemented interfaces, Spring uses JDK dynamic proxies which don't extend the proxy class, but implement all its interfaces, thus you can't find a bean by it's class.
That's why it's always a good practice to autowire your beans by interface rather then by class.
Solution
You can force Spring to use CGLib proxies for AspectJ by annotating you configuration class #EnableAspectJAutoProxy(proxyTargetClass = true).
If you want to use JDK Dynamic proxies, create interface for Comment and then use context.getBean(YourInterfaceName.class).
I have an Interface and multiple implementation. I'm auto wiring the interface in classes for usage. I need to choose different implementation at runtime.
public class Util {
public void getClient();
}
Implementations
public class UtilOne implements Util {
public void getClient() {...}
}
public class UtilTwo implements Util {
public void getClient() {...}
}
#Configuration
public class AppConfig {
#Autowired
#Bean
#Primary
public Util utilOne() {
return new UtilOne();
}
#Autowired
#Bean
public Util utilTwo() {
return new UtilTwo();
}
}
#Component
public class DemoService {
#Autowired
private Util util;
}
For some reason if we are unable to get client in UtilOne, I want to switch to UtilTwo without restarting the app. I want to change the Util object in DemoService to UtilTwo object.
Property active.util will come from DB and can we updated from UI.
It doesn't work this way - if you have a certain implementation of Util wired to, say, class SampleClass (which is a singleton) you can't really change the implementation of the Util to something different without restarting the application context.
So instead of going this way, I suggest an alternative. You say that under certain conditions that evaluate in runtime you want to switch implementations. What kind of condition it is? Is it possible to extract this condition decision logic?
If so, you can autowire a special DynamicUtil that will hold the reference to all the utils and will call the required util depending on the condition:
// represents all possible business 'runtime' outcomes
enum ConditionOutcome {
A, B, C
}
interface ConditionEvaluator {
ConditionOutcome evaluate(); // when called in runtime will evaluate a condition that currently exists in the system
}
interface Util {
void foo();
ConditionOutcome relevantOfOutcome();
}
class Utill1Impl implements Util {
public void foo() {...}
public ConditionOutcome relevantOfOutcome() {return ConditionOutcome.A;}
}
class Utill2Impl implements Util {
public void foo() {...}
public ConditionOutcome relevantOfOutcome() {return ConditionOutcome.B;}
}
class Utill3Impl implements Util {
public void foo() {...}
public ConditionOutcome relevantOfOutcome() {return ConditionOutcome.C;}
}
class DynamicUtil {
private final Map<ConditionOutcome, Util> possibleImpls;
private final ConditionEvaluator evaluator;
public class DynamicUtil(List<Util> allImplementations, ConditionEvaluator evaluator) {
// create a map by calling the 'relevantOfOutcome' per util impl in a loop
this.evaluator = evaluator;
}
public void foo() {
ConditionOutcome key = evaluator.evaluate();
// pick the relevant implementation based on evaluated key
possibleImpls.get(key).foo();
}
}
Now with such a design you can dynamically add new possible outcomes (along with utils that should implement them. You classes in the system will have to autowire DynamicUtil though, so effectively you'll introduce one additional level of indirection but will gain flexibility
class SampleClass { // a business class that will need to work with util capable of being changed during the runtime
#Autowired
private DynamicUtil util;
...
}
You can try approach with delegating proxy. Have a primary Util bean that is just wrapper around actual implementation and allow to change its internal delegate at runtime. In addition you can create something like manager/helper class that holds references to all actual implementation beans to simplify switching between them.
#Component
#Primary
public class DelegatingUtil implements Util {
private Util delegate;
public void setDelegate(Util delegate){ this.delegate = delegate; }
public Util getDelegate(){ return delegate; }
public void getClient() {
return delegate.getClient();
}
}
And where switching logic applies:
// Use #Named or #Qualifier or any other way to obtain references to actual implementations
private Util defaultImpl;
private Util fallbackImpl;
#Autowired
private DelegatingUtil switcher;
public void switchToFallback(){
this.switcher.setDelegate(this.fallbackImpl);
}
Note, this is only schematic example, you should take care about details like bean creation order, injection with qualifiers (maybe conditional), initialization and so on.
Here is a simple approach based on your situation. The main idea is that read active.util property from DB by PropertyService and wrap your Utils into RouteUtil:
#Component
public class RouteUtil {
#Autowired
private PropertyService propertyService;
#Qualifier("one")
#Autowired
private Util utilOne;
#Qualifier("two")
#Autowired
private Util utilTwo;
public void getClient() {
if ("one".equals(propertyService.read("active.util"))) {
utilOne.getClient();
} else {
utilTwo.getClient();
}
}
}
and in DemoService:
#Service
public class DemoService {
#Autowired
private RouteUtil util;
// RouteUtil.getClient() ...
}
You can change active.util to select which Util will be used at runtime without restarting the app.
Spring provides you a solution which I personally didn't like. What you can do is declare a
#MyInterface
List<MyIntercase> myimpls
Where MyInterface is your interface and list will contain all the implementations. However, I (since I didn't like this solution) wrote my own solution, where you can have a static factory that is self-populated by all implementations. So you don't have to inject all your implementations but choose them at run-time from a factory either by class name or by custom-defined name. An additional advantage is that the custom-defined name must be unique per factory. So lets say you have some staged process and for each stage you have your own interface and your own factory. So you can have the same custom defined names for your implementations of different interfaces. Say you working with text formats XML, JSON and CSV and have an interface (and related factory) for say stage-1 stage-2 stage-3. So for each stage-X inteface you can have implemetations named JSON, XML and CSV so all you have to do is have a variable called currentType that will hold one of the values - JSON, XML and CSV and for each stage you can use the factory to get the appropriate implementation:
Stage1Handler handler = stage-1-factory.getInstance(currentValue);
Stage2Handler handler = stage-2-factory.getInstance(currentValue);
Stage3Handler handler = stage-3-factory.getInstance(currentValue);
where Stage[X]Handler is your interface. But this is just an additional benifit. My solution is available in Open-source MgntUtils library. The article about this particular fiture could be found here: Non-intrusive access to "Orphaned" Beans in Spring framework Also, I describe this feature in my library javadoc here. The library could be found as Maven artifact and on Github including source code and Javadoc
I was trying dependency injection in java using the #Inject annotation and I was following the tutorial in this link. According to the tutorial I created the following.
import javax.inject.Inject;
public class GreetingBean {
#Inject private static HelloBean helloBean;
// #Inject
// public GreetingBean(HelloBean helloBean){
// this.helloBean = helloBean;
// }
public static void sayGreeting(){
helloBean.sayHello();
}
public static void main(String[] args) {
GreetingBean.sayGreeting();
}
}
The HelloBean class is as follows.
public class HelloBean {
public void sayHello(){
System.out.println("Hello user");
}
}
On execution I got a null pointer exception which is obvious as helloBean is not initialised. According to what I understood from the tutorial #Inject is supposed to take care of that. I feel that I have to do something more to make this work but I could not find any reference. Can someone help me in this matter.
Take a look here if you want to use CDI with a standard Java application. (This is using the reference CDI implementation, Weld)
I have a Spring project that runs locally during the development/debugging phase,
while on production it will be loaded on a PaaS.
My problem is that there are certain instruction that must be executed depending on the platform!
Currently I check a boolean (using #ConfigurationProperties) that I read from the application.properties, but I'm wondering if there's a smarter way because I have also to change the boolean when I push in production.
You should use Spring profiles and implement your check a little bit mor object oriented:
I assume your code looks something like this, and Logic is a spring managed bean:
#Component
public class Logic {
public void doIt() {
doMoreLogic();
if (yourProperty == true) {
your();
certain();
instructions();
}
doWhateverYouWant();
}
}
If you extract the certain logic to a class, then you can do it more the object oriented way:
public interface PlatformDependentLogic {
void platformInstructions();
}
#Component #Profile("dev")
public class DevLogic implements PlatformDependentLogic {
public void platformInstructions() {
your();
certain();
instructions();
}
}
#Component #Profile("!dev")
public class NoopLogic implements PlatformDependentLogic {
public void platformInstructions() {
// noop
}
}
Now you can reference the logic by doing this in your Logic bean:
#Component
public class Logic {
private #Autowired PlatformDependentLogic platformLogic;
public void doIt() {
doMoreLogic();
platformLogic.platformInstructions();
doWhateverYouWant();
}
}
Of course you can utilize the spring boot specific #ConditionalOnProperty instead of the #Profile annotation like this:
#ConditionalOnProperty(name="your.property", hasValue="dev")
To get a better understanding of this annotation and how it workds you should read the official documentation of #ConditionalOnProperty
May I suggest using Gradle product flavors for your local/Paas environments, something similar to this:
https://code.tutsplus.com/tutorials/using-gradle-build-variants--cms-25005
I have been studying #Produces annotation of CDI dependency injection from here. I just created my own same example. However, I am facing with ambiguous dependency.
public interface Bank {
public void withdrawal();
public void deposit();
}
public class BankOfAmerica implements Bank {
#Override
public void withdrawal() {
System.out.println("Withdrawal from Bank of America");
}
#Override
public void deposit() {
System.out.println("Deposit to Bank of America");
}
}
public class BankFactory {
#Produces
public Bank createBank() {
return new BankOfAmerica();
}
}
And this is the class which bean is get injected.
public class ProducesExample {
#Inject
private Bank bankOfAmerica;
public void callBanksWithdrawal() {
bankOfAmerica.withdrawal();
}
}
I appreciate for any help.
EDIT: I know this a kind of duplicate of this question. However, in the tutorial which I shared, it says it should work. Moreover, there is only one type of bean so no need use #Default or #Alternatives but still get confused about why it is not working.
The tutorial is a bit ambiguous (pun intended) about which classes should be deployed simulataneously in each step, so I wouldn't worry about that too much.
The answer to the other question you linked does match your case. BankOfAmerica is a bean of type Bank (in CDI 1.0 or in CDI 1.1+ with explicit beans), and your producer method is another bean of the same type, hence the ambiguous resolution.
One thing that can be helpful is your beans.xml file.
If you want to have a factory (using #produces) you cannot have the bean-discovery-mode="all". If you have the all option than you will get Ambiguous dependencies exception cause all your implementations will be auto scanned as possible dependencies ( what in my opinion is a bad performance option ).
So put bean-discovery-mode="annotated" , leave your implementations cdi-annotation free and use #Dependent in the factory and #produces in the build method.
You have to add #BankProducer annotation like that :
public class BankFactory {
#Produces
#BankProducer
public Bank createBank() {
return new BankOfAmerica();
}
}