autowiring webapplicationcotnext in my spring 3.2 tests - java

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.

Related

MockMvc Spring Boot springSecuirtyChainCannotBeNull issue

Can someone point me to what could be wrong in below code. It is a boot spring 2.6.7 application. When test profile is running, it throws error for all tests like below.
java.lang.IllegalStateException: springSecurityFilterChain cannot be null. Ensure a Bean with the name springSecurityFilterChain implementing Filter is present or inject the Filter to be used
#AutoConfigureMockMvc
#SpringBootTest(classes = some.class)
#ActiveProfiles("test")
public class someTest {
#Autowired
private MockMvc mvc;
#Autowired
private WebApplicationContext webAppContext;
#MockBean
private SomeBean someBean;
#SpyBean
private SomeSpyBean someSpyBean;
#BeforeEach
public void setup() {
mvc = MockMvcBuilders
.webAppContextSetup(webAppContext)
.apply(springSecurity())
.build();
}
#Test
public void SomeTest1() throws Exception {
String text = "text1";
when(someBean.findStuff(text).thenReturn(Optional.of(new Thingie()));
mvc.perform(multipart("/api/somepath/")
.andExpect(status().isNotFound());
verify(someSpyBean).doStuff();
}
#Test
public void SomeTest2() throws Exception {
String text = "text2";
when(someBean.findStuff(text).thenReturn(Optional.of(new Thingie()));
mvc.perform(multipart("/api/somepath/")
.andExpect(status().isFound());
verify(someSpyBean).doStuff();
}
}

calling a method from a different class in springBoot

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.

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;
}
...
}

Cannot use spring ApplicationContext in logback appender

Technology:
spring boot,logback
I write a mail appender to reuse spring managed JavaMailSender.In order to get the JavaMailSender instance in spring ,I have this global static field in class
public class ApplicationContextHolder implements ApplicationContextAware {
public static ApplicationContext applicationContextHolder = null;
#Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
applicationContextHolder = applicationContext;
}
}
In appender , I use the static field directly
if (javaMailSender == null) {
javaMailSender = ApplicationContextHolder.applicationContextHolder.getBean(JavaMailSender.class);
}
The problem is that field applicationContextHolder is null.I debug setApplicationContext method
and find applicationContext is injected.I thought the classloader may not the same one ,but Thread.currentThread().contextClassLoader has the same toString value.
Anyone knows why?How can I get applicationContext in appender?
start + in controller + in appender

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