calling a method from a different class in springBoot - java

i want to call a method which is containing applicationContext which works fine when run independently but when i try calling it from a different class appContext.getBean(DataSource.class) returns null.
public class Action {
private static Logger log = LoggerFactory.getLogger(Action.class);
#Autowired
MessageConfigProperties messageProperties;
#Autowired
AutomatorApp automatorApp;
#Autowired
Apps gapps;
#Autowired
Deploy d;
#Autowired
Deploy depstatusChk;
#Autowired
private ApplicationContext appContext;
#Autowired
CreateSaltFileService createSaltFile;
#Autowired
DeployFactory depFactory;
#Autowired
IMoveAppsService moveAppsService;
#Autowired
IUserEnvironmentService userEnvService;
#Autowired
IEnvironmentService envService;
#Autowired
Session session;
private Logger logger = LoggerFactory.getLogger(Action.class);
private ServletContext context;
#Context
public void setServletContext(ServletContext context) {
System.out.println("servlet context set here");
this.context = context;
}
#POST
#Path("/register/")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
#RequiresRoles("admin")
#RequiresPermissions("automator:register")
public Session register(Session credentials, #BeanParam Session springContext) throws AppException {
System.out.println("into action class");
System.out.println("-->>>" +appContext.getBean(DataSource.class));
appContext.getBean(DataSource.class);
logger.info(messageProperties.getGreetings());
// logger.trace("Inside Session");
System.out.println("Inside Session");
credentials.setDatasource(springContext.getDatasource());
when this Action method is called from
this method agentGroup in different class
#POST
#Produces(MediaType.APPLICATION_JSON)
#ApiOperation(value = "Get List of agent group", response =
AgentGroup.class, responseContainer = "List")
public ArrayList<AgentGroup> agentGroup(Session credentials, #BeanParam Session springContext) throws AppException, ConfigException, InterruptedException {
Session r=objA.register(credentials, springContext);
int sessionId=r.getSessionId();
}

You #Autowire ApplicationContext appContext just to get datasource (appContext.getBean(DataSource.class)).
Why do not #Autowire DataSource datasource directly?
It will make make business logic of your Action class independend from Spring.
If you really want to access ApplicationContext you may try another approach
make Action implements ApplicationContextAware
private ApplicationContext ctx;
#Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
ctx = applicationContext;
}
See Circular dependency in Spring for details.
edit:
your Action class has no annotation. no org.springframework.web.bind.annotation. RestController, no #Component or #Service. are you sure it is managed by Spring? if it is just created using new then Autowire will not work and fields will be null.

Related

Application Context not injected in an `#Configuration` annotated class

I have a setup like:
#Configuration
public class MyConfig {
#Autowired
ApplicationContext applicationContext;
#Bean
public MyBean myBean() {
return applicationContext.getAutowireCapableBeanFactory().createBean(MyBean.class);
}
}
Soon as I launch my Application, Spring tries to create myBean even before injecting applicationContext. As the latter is null, it will cause a NullPointerException in the method myBean().
Strangely, injecting the Application Context works in some other #Configuration classes, but not in the one mentioned above.
Is there a way force the injection of applicationContext before the method myBean() is called?
I don't think that you have the guarantee that the fields declared with #Autowired be always loaded before the invocation of the methods declared with #Bean .
To ensure that the ApplicationContext object is valued, you could make your configuration class implement ApplicationContextAware.
#Configuration
public class MyConfig implements ApplicationContextAware {
private ApplicationContext context;
public void setApplicationContext(ApplicationContext context) {
this.context = context;
}
...
}

spring depenency injection with annotations

I'm just starting with DI and Spring. I have these two Components (pseudocode)
#Component
public class AuthHandlerImpl extends ChannelInboundHandlerAdapter implements AuthHandler {
#Autowired
AuthService authService;
#Override
channelRead(ChannelHandlerContext ctx, Object msg) {
authService.authenticate(msg); // want to pass ctx to constructor of authService
}
}
#Component
public class AuthServiceImpl implements AuthService {
private CustomerService customerService;
private ChannelHandlerContext ctx;
#Autowired
public AuthServiceImpl(CustomerService customerService, ChannelHandlerContext ctx) {
this.customerService = customerService;
this.ctx = ctx;
}
}
What I'm trying to achieve is have AuthService injected with the constructor parameters, where one of the constructor arguments is the ChannelHandlerContext from the ChannelInboundHandlerAdapter class. Not sure if that's possible or not.
Yes, it's possible, but CustomerService and ChannerHandlerContext must be defined as spring beans (like #Component, #Service, #Controller or #Bean annotations) in order to be autowired in the constructor. You can check this post to get more information about the topic.

autowiring webapplicationcotnext in my spring 3.2 tests

Following the instructions here, but i get the error unable to autowire WebApplicationContext.
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("applicationContext-test.xml")
#WebAppConfiguration
public class AjaxTest {
#Autowired
private WebApplicationContext webApplicationContext; //FAILS
But this compiles :
#Autowired
ServletContext servletContext;
private WebApplicationContext webApplicationContext = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);
And I don't understand why.
Edit
It runs fine using maven, it was my editor intellij showing an incorrect auto compile message, a bug in fact.
Your test class should implement ApplicationContextAware interface:
public class ApplicationContextProvider implements ApplicationContextAware {
private static ApplicationContext applicationContext = null;
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
Spring will automatically inject the application context.

How to get an object with transaction in Spring?

I have a Service class like this:
#Service
public class CompanyServiceImpl implements CompanyService {
#Autowired
private CompanyDAO companyDAO;
#Transactional
public void addOrUpdateCompany(Company company) {
companyDAO.addOrUpdateCompany(company);
}
}
Normally, I can have an instance of CompanyService from Spring by:
#Autowired
CompanyService companyService;
But, in some cases, I want to create/get an instalce of CompanyService without #Autowired like this:
CompanyService companyService = XXX.getxxx("CompanyService");
Is there any ways I can do this?
Other way is
#Component
public class ContextHolder implements ApplicationContextAware {
private static ApplicationContext CONTEXT;
public void setApplicationContext(ApplicationContext applicationContext) {
CONTEXT = applicationContext;
}
public static ApplicationContext getContext() {
return CONTEXT;
}
}
And then
CompanyService service = ContextHolder.getContext().getBean(CompanyService.class);
If I understand you correctly, you mean something like - ServiceLocatorFactoryBean
with it you can call somthing like MyService getService(String id)).
Another way, will be to implement some kind of a controller service that will have all other services autowired to it, and will hold a map from their string id to actual instances.
In my opinion the second option is better, since it's more manageable and clear.
Hope that helps you.
You can do it. You need to instancate the application context and then get your been.
Resource res = new FileSystemResource("beans.xml");
XmlBeanFactory factory = new XmlBeanFactory(res);
or
ClassPathResource res = new ClassPathResource("beans.xml");
XmlBeanFactory factory = new XmlBeanFactory(res);
or
ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext(
new String[] {"applicationContext.xml", "applicationContext-part2.xml"});
// of course, an ApplicationContext is just a BeanFactory
BeanFactory factory = (BeanFactory) appContext;
and use:
MyObject my = (MyObject)factory.getBean(NAME_OF_YOUR_BEAN);

How to inject ApplicationContext itself

I want to inject an ApplicationContext itself to a bean.
Something like
public void setApplicationContext(ApplicationContect context) {
this.context = context;
}
Is that possible in spring?
Previous comments are ok, but I usually prefer:
#Autowired private ApplicationContext applicationContext;
Easy, using the ApplicationContextAware interface.
public class A implements ApplicationContextAware {
private ApplicationContext context;
public void setApplicationContext(ApplicationContext context) {
this.context = context;
}
}
Then in your actual applicationContext you only need to reference your bean.
<bean id="a" class="com.company.A" />
Yes, just implement the ApplicationContextAware -interface.
I saw some comments above about #Autowired not working still. The following may help.
This will not work:
#Route(value = "content", layout = MainView.class)
public class MyLayout extends VerticalLayout implements RouterLayout {
#Autowired private ApplicationContext context;
public MyLayout() {
comps.add(context.getBean(MyComponentA.class)); // context always null :(
}
You must do this:
#Autowired
public MyLayout(ApplicationContext context) {
comps.add(context.getBean(MyComponentA.class)); //context is set :)
}
or this:
#PostConstruct
private void init() {
comps.add(context.getBean(MyComponentA.class)); // context is set :)
}
Also note that Upload is another component that must be set within the scope of #PostConstruct. This was a nightmare for me to figure out. Hope this helps!
I almost forgot to mention that the #Scope annotation may be necessary for your Bean, as seen below. This was the case when using Upload within a Bean because the UI is not instantiate/attached prior to the Bean being created and will cause a Null Reference Exception to be thrown. It won't do so when using #Route, but will when using #Component - so the latter is not an option and if #Route is not viable, then I would recommend using #Configuration class to create the bean with the prototype scope.
#Configuration
public class MyConfig {
#Bean
#Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE, proxyMode = ScopedProxyMode.TARGET_CLASS)
public MyComponentA getMyBean() {
return new MyComponentA();
}
}
Special solution: get Spring beans from any (non Spring) classes
#Component
public class SpringContext {
private static ApplicationContext applicationContext;
#Autowired
private void setApplicationContext(ApplicationContext ctx) {
applicationContext = ctx;
}
public static <T> T getBean(Class<T> componentClass) {
return applicationContext.getBean(componentClass);
}
}

Categories