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)
Related
I'm trying to develop my first java Spring Bboot app that calls Strava API and gets my activities for the given period of time.
I've registered my app on Strava's website and got client_id and client secret.
I've generated spring-swagger-codegen-api-client and awtowired the client to the app.
#Configuration
public class StravaIntegrationConfiguration {
#Bean
public ActivitiesApi stravaApi(){
return new ActivitiesApi(apiClient());
}
#Bean
public ApiClient apiClient(){
return new ApiClient();
}
}
Then I use this bean in AdapterClass
public class Adapter {
#Autowired
private static ActivitiesApi activitiesApi;
public static void getActivities(Integer before, Integer after, Integer page, Integer perPage) {
final List<SummaryActivity> loggedInAthleteActivities = activitiesApi.getLoggedInAthleteActivities(before, after, page, perPage);
System.out.println("ВСЕГО АКТИВНОСТЕЙ"+ loggedInAthleteActivities.size());
}
}
#SpringBootApplication
#Import(StravaIntegrationConfiguration.class)
public class App {
public static void main(String[] args) throws SQLException {
SpringApplication.run(App.class);
Adapter.getActivities(1636130496, 1635529296, 1, 30);
}
}
When I run this code I get NPE, because activitiesApi is null.
What is the problem? Please kindly advise.
Does it concern authentication? Could you advise also any code sample on how to make Strava authentication in my app?
It has nothing to do with Strava authentication. It is related to Spring context and Spring Beans and how to inject them. As already mentioned you can't autowire Spring-managed beans in static fields (it makes no sense actually). Having said that you need to fix that first:
#Component
public class Adapter {
#Autowired
private ActivitiesApi activitiesApi;
public void getActivities(Integer before, Integer after, Integer page, Integer perPage) {
final List<SummaryActivity> loggedInAthleteActivities = activitiesApi.getLoggedInAthleteActivities(before, after, page, perPage);
System.out.println("ВСЕГО АКТИВНОСТЕЙ"+ loggedInAthleteActivities.size());
}
}
Also, note that the method changed from a static one to an instance one and that the annotation #Component was added to the class. The reason is that a Spring-managed bean can only be injected into other Spring-managed beans.
Additionally, it seems to me that you are trying to do something after the Spring context has been initialized. One possible way to do this is creating a bean that implements the ApplicationListener interface:
#Component
public class StartupApplicationListener implements ApplicationListener<ContextRefreshedEvent> {
#Autowired
private Adapter adapter;
#Override
public void onApplicationEvent(ContextRefreshedEvent event) {
adapter.getActivities(1636130496, 1635529296, 1, 30);
}
}
This means that you can and you should remove the line Adapter.getActivities(1636130496, 1635529296, 1, 30); from your main class:
#SpringBootApplication
#Import(StravaIntegrationConfiguration.class)
public class App {
public static void main(String[] args) throws SQLException {
SpringApplication.run(App.class);
}
}
Finally, and as a side note, please consider using constructor injection instead of field injection. It has a couple of advantages over field injection: making the class easier to unit test, allowing the objects to be immutable, explicitly definition of which dependencies are mandatory, etc... (you can read more at https://reflectoring.io/constructor-injection/).
I have this web application built with Spring and Vaadin, in which I wanted to do this, for the sake of convenience:
Create a utility class that wraps a Spring service, and allows the use of its static methods throughout the application, without having to worry about injecting this service everywhere, like so:
String configurationValue = ConfigurationUtil.getString("some.property.key");
If you work with Vaadin, you might see how convenient this is, because the whole presentation layer is written in Java and you can't always inject Spring services into your Vaadin components as these Vaadin components are not always Spring components themselves.
So this is my utility class:
public final class ConfigurationUtil {
// this is the spring service:
private static ConfigurationService configurationService;
public static void setConfigurationService(final ConfigurationService configurationService) {
ConfigurationUtil.configurationService = configurationService;
}
public static String getString(final String key) {
return configurationService.getString(key);
}
}
This is my service:
#Service("configurationService")
public class ConfigurationServiceImpl implements ConfigurationService, BeanFactoryAware {
private final FrameworkService frameworkService;
#Autowired
public ConfigurationServiceImpl(final FrameworkService frameworkService) throws IOException, ConfigurationException {
// this is where I set this service bean to the utility class
ConfigurationUtil.setConfigurationService(this);
this.frameworkService = frameworkService;
}
public String getString(String key) {
// code that retrieves a configuration value from our configuration files
}
}
My question here is: I'm a bit worried about this causing a bottleneck to access the configuration service, as multiple threads will be calling it, from multiple user sessions. Would this be a problem? Please explain why. Also, feel free to point out other problems with this solution.
I suggest to create a bean that implements ApplicationContextAware like this:
#Component
public class ApplicationContextProvider implements ApplicationContextAware {
private static ApplicationContext context;
#Override
public void setApplicationContext(ApplicationContext ac) {
context = ac;
}
public static String getString(final String key) {
ConfigurationService configurationService = context.getBean(ConfigurationService.class);
return configurationService.getString(key);
}
public static <T> T bean(Class<T> beanType) {
return context.getBean(beanType);
}
}
You can create a method like in the example to give static access to Spring Beans or what you requested to get a String from your ConfigurationService.
Btw. I use this a lot in Vaadin applications because I don't want to make every component a Spring Bean.
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
I have a maven multi module project. When trying to Access a injected bean i get a Nullpointer Exception.
this is the main Function that startsthe application
public class App {
public static void main(String[] args) {
System.out.println("Startpoint");
DecisionMaker decisionMaker = new DecisionMaker();
decisionMaker.run();
}
}
this is what i do in the DecisionMaker
public class DecisionMaker {
#Inject
GameListener gm;
#Inject
BasicProductionManager basicProductionManager;
public DecisionMaker() {
System.out.println("this is the decisionmaker");
System.out.println(gm.toString());
}
so this is not an bean but a normal pojo
the gamelistener is a Applicationscoped bean which i want to inject.
#Named
#ApplicationScoped
public class GameListener extends DefaultBWListener {
#Inject
Event<OnFrameEvent> onFrameEvent;
public Mirror mirror = new Mirror();
public Game game;
public Player self;
#PostConstruct
public void init() {
System.out.println("init listener");
}
the nullpointer gets thrown in the constructor of the DecisionMaker. The #PostConscrutct init method is not called
I looked into similar question but all i found is that i needthe PostConstruct method which i already have.
you can't instantiate DecisionMaker yourself. the whole point of CDI is to give it control of creating and managing beans.
check out this article to see how to use CDI in JAVA SE.
I am trying to use #Async annotation provided by spring. Going through some of the blogs I found there are the following constraints for using it:
It must be applied to public methods only
Self-invocation – calling the async method from within the same class – won’t work
I have a method which is getting called from the same class which I want to mark #Async. Is there any way of achieving it from the same class?
In Spring v4.3+ you can use self injection, and call the method on the self injected reference.
So for example:
#Component
public class SomeClass {
#Autowired
private SomeClass selfInjected;
public void someMethod() {
selfInjected.someOtherMethod();
}
#Async
public void someOtherMethod(){
...;
}
}
Updated as OP is using version before 4.3:
This will work for you.
#Component
public class SomeClass {
#Autowired
private ApplicationContext applicationContext;
private SomeClass selfInjected;
#PostConstruct
private void init() {
selfInjected = applicationContext.getBean(SomeClass.class);
}
}
Or
The other option is to extract the method to separate class and autowire it. I would personally explore this option before doing the above method.