Have a look at following code:
#Local
public interface MyService {
void printMessage();
}
#Stateless
public class MyServiceImpl implements MyService {
#Override
public void printMessage() {
System.out.println("Hello from MyService.");
}
}
#Stateless
#Named
public class Application {
#EJB
public MyService sampleService;
private static Application getApplication() throws NamingException {
Properties properties = new Properties();
properties.setProperty(EJBContainer.APP_NAME, "admin");
EJBContainer.createEJBContainer(properties); //.getContext();
Context context = new InitialContext();
Application application = (Application) context.lookup("java:global/admin/classes/Application");
return application;
}
public static void main(String[] args) throws NamingException {
Application application = getApplication();
application.start(args);
}
private void start(String[] args) {
sampleService.printMessage();
}
}
I expected to have simpletService instance available at start() operation, but it is equal to null. All classes are part of one project (placed in separated files). Where I have made mistake? Thanks for advice.
Finally I have found solution. When I changed start() operation to be public and injection started work fine.
Related
I'm trying to run Hazelcast client application with Spring Boot without XML/YAML file but I can't find a way to manage my Hazelcast instance via Spring. This is my code
#Configuration
public class ConfigurationClass {
#Autowired
private Environment env;
#Bean
public ClientConfig clientConfig() {
ClientConfig clientConfig = new ClientConfig();
ClientNetworkConfig networkConfig = clientConfig.getNetworkConfig();
networkConfig.addAddress("127.0.0.1:5701").setSmartRouting(true).addOutboundPortDefinition("34700-34710").setRedoOperation(true).setConnectionTimeout(5000);
return clientConfig;
}
#Bean
public HazelcastInstance hazelcastInstance(ClientConfig clientConfig) {
return HazelcastClient.newHazelcastClient(clientConfig);
}
}
And when I try to Autowire Hazelcast instance into main class I get NULL. Main class code
public class HazelcastServer implements Serializable {
private static final long serialVersionUID = -1798311083790835361L;
#Autowired
private static HazelcastInstance hazelcastInstance;
public static void main(String[] args) {
System.out.println("hazelcastInstance: " + hazelcastInstance);
}
}
You need to use a CommandLineRunner so that Spring builds your context (in other words, creates your #Beans and autowires them)
See the tutorial here for a good start:
https://spring.io/guides/gs/spring-boot/
Basically, instead of the public static void main you need to do something like this:
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
#Bean
public CommandLineRunner commandLineRunner(ApplicationContext ctx) {
return args -> {
System.out.println("Let's inspect the beans provided by Spring Boot:");
String[] beanNames = ctx.getBeanDefinitionNames();
Arrays.sort(beanNames);
for (String beanName : beanNames) {
System.out.println(beanName);
}
};
}
}
The #SpringBootApplication and SpringApplication.run part tells Spring to do it's magic, read the tutorial I linked for the details.
I am implementing custom annotation processing using Spring AOP. I have below code.
public class CacheDemo {
private static ApplicationContext applicationContext;
public static void main(String args[])
{
applicationContext =
new AnnotationConfigApplicationContext(ApplicationConfiguration.class);
}
}
//Application Configuration
#Configuration
#ComponentScan("Demo")
#Component
public class ApplicationConfiguration implements ApplicationContextAware {
#Autowired
TestCacheDemo testCacheDemo;
private static ApplicationContext applicationContext;
#Override
public void setApplicationContext(ApplicationContext ctx) throws BeansException {
applicationContext = ctx;
}
#Bean
public void testCacheDemoIntialize()
{
testCacheDemo.setApplicationContext(applicationContext);
testCacheDemo.test();
}
}
//CustomAnnotation processor
#Aspect
#Component
public class CustomAnnotationAspect {
#Autowired
private AbstractCacheService cacheService;
#Around("#annotation(Demo.CustomCacheable)")
public Object customCacheable(ProceedingJoinPoint joinPoint) throws Throwable { // This method is not called at all
joinPoint.proceed();
// Some other code to follow
}
// Custom Annotation
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface CustomCacheable {
}
// Annotation user
#Component
public class CacheProvider
{
#Autowired
AbstractCacheService abstractCacheService;
CacheManager<String,String> cacheManager;
#PostConstruct
void init()
{
cacheManager = CreateCache.create(s -> {return s.toUpperCase();});
abstractCacheService.setCacheManager(cacheManager);
}
#CustomCacheable
String getCacheValue(String s)
{
String str=s.toUpperCase();
return str;
}
}
For testing purpose I have created the below bean
#Component
public class TestCacheDemo extends TimerTask
{
private ApplicationContext applicationContext;
private Timer timer;
#Autowired
CacheProvider cacheProvider;
void test()
{
System.out.println("Called test");
for (String beanName : applicationContext.getBeanDefinitionNames()) {
System.out.println(beanName);
}
//CacheProvider cacheProvider = applicationContext.getBean(CacheProvider.class);
//cacheProvider.getCacheValue("Hello");
timer = new Timer();
timer.schedule(this,1000,3000);
}
void setApplicationContext(ApplicationContext ctx)
{
applicationContext=ctx;
}
#Override
public void run() {
cacheProvider.getCacheValue("Hi");
}
}
Whenever the application is started it will call the test method of the TestCacheDemo Class and sets the timer to be fired after 3 secs so that I can call the annotated method getCacheValue from inside the run method of the timer task. But when the annotated method is called the annotation processor is not invoked. Hence I am unable to do annotation processing. Please let me know where is the problem?
To use AspectJ in spring boot you must enable it.
You should add the following annotation to your application main class (CacheDemo) or application configuration class.
#EnableAspectJAutoProxy
I am running springboot application with TimerTask my object of service is showing null.
I have tried various methods but unable to get rid of the Null pointer exception.
main class .
#SpringBootApplication
#ComponentScan(basePackages = {"com.comments.demo"})
public class NotifyMain {
#Autowired
static
NotifyService notifyService;
public static void main(String[] args) {
Timer timer1 = new Timer();
timer1.schedule(notifyService, 10, 10);
SpringApplication.run(NotifyMain.class, args);
}
}
Service class
package com.comments.demo;
#Service
#Configurable
public class NotifyService extends TimerTask{
#Autowired
ListNotification listElement;
#Override
public void run() {
Notification notification= new Notification();
listElement.add(notification);
}
ListNotification and Notification class are working fine.
console
Exception in thread "main" java.lang.NullPointerException
at java.util.Timer.sched(Timer.java:399)
at java.util.Timer.schedule(Timer.java:248)
at com.comments.demo.NotifyMain.main(NotifyMain.java:22)
here is the code of ListNotification
package com.comments.demo;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
#Component
public class ListNotification {
private List<Notification> notifications = new ArrayList<>();
#Autowired
private NotificationObserver notificationObserver;
public void setNotifications(List<Notification> notifications) {
this.notifications = notifications;
}
public void add(Notification notification) {
notifications.add(notification);
notifyListeners(notification);
}
private void notifyListeners(Notification newValue) {
notificationObserver.observation(newValue);
}
}
first I was getting listElement object null. so i got that instead of using the new NotifyService() in parameter of schedule method i should use the injected bean but how to do it I don't know.
You cannot autowire or manually wire static fields in Spring. Instead, try setter injection:
private static NotifyService notifyService;
#Autowired
public void setNotifyService(NotifyService notifyService){
NotifyMain.notifyService= notifyService;
}
But still, there won't be any guarantee if NotifyService is injected before used. You can also try 2nd approach:
private static NotifyService notifyService;
#Autowired
private NotifyService autowiredNotifyService; //same as above but non-static this time. And you autowire this one.
#PostConstruct
private void init() {
NotifyMain.notifyService = this.autowiredNotifyService;
}
3rd Approach -> Use constructor injection:
private static NotifyService notifyService;
#Autowired
public NotifyMain(NotifyService notifyService){
NotifyMain.notifyService= notifyService;
}
Do know that autowiring to static field is undesirable. One should NOT do it.
Since your application is more like a console based application, this approach can also be taken:
#SpringBootApplication
public class NotifyMain implements CommandLineRunner {
#Autowired
private NotifyService notifyService;
public static void main(String[] args) {
SpringApplication.run(NotifyMain.class, args);
}
#Override
public void run(String... args) {
Timer timer1 = new Timer();
timer1.schedule(notifyService, 10, 10);
}
run method inside main class is the starting point of the application. I don't think before starting the application you can autowire objects. try doing this
#SpringBootApplication
public class NotifyMain {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(NotifyMain.class, args);
NotifyService notifyService = (NotifyService) context.getBean(NotifyService.class);
context.getBean(Timer.class).schedule(notifyService, 10, 10);
}
}
I have an application that builds upon the Spring framework. To implement some of the requirements I had to provide my own implementation of the ApplicationContext.
Now that I moved to spring-boot I am wondering if there is any way to force the start up to use my implementation of the ApplicationContext?
EDIT: Provide some code
public class OpenPatricianSpringBootStandaloneApplication implements CommandLineRunner {
private static Logger logger = LogManager.getLogger(OpenPatricianSpringBootStandaloneApplication.class);
public static void main(String[] args) throws Exception {
SpringApplication.run(OpenPatricianSpringBootStandaloneApplication.class, args);
}
#Override
public void run(String... args) throws Exception {
String jreVersion = (String) System.getProperties().get("java.version");
if (!jreVersion.startsWith("1.8")) {
logger.error("JRE must be of version 1.8");
System.out.println("JRE must be of version 1.8");
System.exit(1);
}
logEnvironment();
CommandLineArguments cmdHelper = new CommandLineArguments();
Options opts = cmdHelper.createCommandLineOptions();
CommandLine cmdLine = cmdHelper.parseCommandLine(opts, args);
if (cmdLine.hasOption(CommandLineArguments.HELP_OPTION)){
cmdHelper.printHelp(opts);
System.exit(0);
}
if (cmdLine.hasOption(CommandLineArguments.VERSION_OPTION)) {
System.out.println("OpenPatrician version: "+getClass().getPackage().getImplementationVersion());
System.exit(0);
}
cmdHelper.persistAsPropertyFile(cmdLine);
unpackPlugins();
ServerLauncher.initializeApplicationContext(StandaloneConfiguration.class);
OpenPaticianApplicationWindow.startClientUI(new String[0]);
}
The context is created in the second last line:
public static void initializeApplicationContext(Class clientServerContextClass) {
Preconditions.checkArgument(baseServerContext == null, "Application baseServerContext is already initialized");
baseServerContext = new DependentAnnotationConfigApplicationContext(clientServerContextClass);
logger.info("Initialize baseServerContext (" + baseServerContext.hashCode() + ") with class "+clientServerContextClass.getName());
((AbstractApplicationContext)baseServerContext).registerShutdownHook();
}
The DependentAnnotationConfigApplicationContext is the ApplicationContext implementation I am using. And this is how the spring applicationn is created without spring boot.
There is an interface ApplicationListener which can be implemented and which takes many listeners like Refresh, Start.
public class ApplicationListenerBean implements ApplicationListener<ContextRefreshedEvent> {
#Override
public void onApplicationEvent(ContextRefreshedEvent event) {
ApplicationContext applicationContext = event.getApplicationContext();
// now you can do applicationContext.getBean(...)
// ...
}
}
Hope this will help.
i create simple spring project and i need to use annotation #Autowired but when i run project, i get exception NullPointerException.
This is my classes:
Main.java
public class Main {
#Autowired
private static InjectClass injectClass;
public static void setInjectClass(InjectClass injectClass) {
Main.injectClass = injectClass;
}
public static void main(String[] args) {
injectClass.hello(); //NullPointerException
}
}
ConfigurationBean
#Configuration
public class ConfigurationBean {
#Bean
public InjectClass injectClass(){
return new InjectClass();
}
}
InjectClass
public class InjectClass {
public void hello(){
System.out.println("Autowired success!");
}
}
You need to initiate application contex before using any bean.
You can do it by writing following code in starting of your main method.
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(
ConfigurationBean.class);