Spring Junit test issue - spring

I am creating Junit test cases in Spring.
private static BeanFactory servicefactory = null;
private static BookingProcessService bookingProcessService;
#BeforeClass
public static void setUpBeforeClass() throws Exception{
try{
String[] configFiles = {"applicationcontext-Service.xml","applicationcontext-Hibernate.xml","applicationContext-dao.xml"};
ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext(configFiles);
servicefactory = (BeanFactory) appContext;
bookingProcessService = (BookingProcessService) servicefactory.getBean("bookingProcessService");
}catch (Exception e){
e.printStackTrace();
}
}
Here BookingProcessService is an interface and its implementation class is BookingProcessServiceImpl.java.
In spring configuration files, there is no bean id defined for that.
Is there any way I can use the 'bookingProcessService' for invoking the actual method definition written in BookingProcessImp.java in my test methods?

If u are configuring this test I recommend to use Annotations, will be more clear.
Usually in your "applicationcontext-Service.xml" must have the bean defined with the Implementation, and is the classes where you would use the Interface of this class.
With that you would not coupling code with implementation.
In this example, simple must do the next:
#Autowired
private BookingProcessService bookingProcessService;
The annotation #Autowired from Spring will do the IOC from your xml configuration "applicationcontext-Service.xml".

Related

Receiving Objects from the IoC Container - Spring

have have these two apps which actually do the same (if I am correct)
#SpringBootApplication
public class DemoApplication {
#Autowired
HelloWorld helloWorld;
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
#Bean
public CommandLineRunner run() {
helloWorld.setMessage("wow");
return (load) -> {
helloWorld.getMessage();
};
}
}
and
public class MainApp {
public static void main(String[] args) {
ApplicationContext context = new
ClassPathXmlApplicationContext("Beans.xml");
HelloWorld obj = (HelloWorld) context.getBean("helloWorld");
obj.getMessage();
}
}
both uses
#Component
public class HelloWorld {
private String message;
public void setMessage(String message) {
this.message = message;
}
public void getMessage() {
System.out.println("Your Message : " + message);
}
}
The only difference at the helloWord obj is, that if I use the MainApp-class in my program, then the helloWorld class doesn't need the #Component annotation.
My Question:
If I am correct the SpringBoot annotation makes it unnecessary to define a ClassPathXMLApplicationContext. #Autowire does that for me.
I am now interested if I AutoWire lets say 100 objects at the beginning, all these objects are now in the IoC container correct?
If so: Is not possible to just hand out that container in a CTOR of another class and have access to all saved objects there like:
(HelloWorld) context.getBean("helloWorld"); or
(someRandomClass) context.getBean("someRandomClass")
public CTOR(IOCContainer container) {
this.container = container;
}
Instead of that implementation
public CTOR(HelloWorld helloWorld, SomeRandomClass someRandomClass) {
this.helloWorld = helloWorld;
this.someRandomClass = someRandomClass;
}
And if that is possible, how can I do that?
(There is no use case/task behind my question, i am just interested if that is possible)
The XML'ish way of configuration where you define your bean and wiring via
<bean ... etc. pp.
can be completely replaced by either using
#Component
public class MyClass ....
or by
#Bean
public MyClass myClass() {return new MyClass();}
definition in a configuration class. Both ways place the entity in the IoC container of Spring.
The #Autowire just informs the IoC container of Spring that you would like to have a bean fulfilling the contract of the entity marked with #Autowire injected into this place.
In order to get access to the container you just need to inject the ApplicationContext where you would like to have it.
There are two ways of creating beans in Spring. One is through XML config and the other is through annotation config. Annotation config is the preferred approach as it has lot of advantages over xml config.
Spring boot doesnt have any thing to do with annotation or xml config. Its just a easy way to boot spring application. #Component creates the object of the annotated bean in the application context. #Import or #ImportResource are the annotations used to load the configs from Annotations or through XML configs in Spring boot. With Spring boot u need not create ClassPathXMlCOntext or AnnotationContext objects, but its created internally by spring boot.
#Autowired is a way of getting the beans into any object by injecting rather than tight coupling to the code. Spring container(Application context) do this job of injecting. Just autowiring any class wont create the objects in Spring context. Its just an indication for the Spring context to set the object in the Application context here. You need to create them explicitly inside a xml config/ or annotations like #Component #Service others.
There is no need of hand out of container anywhere. U can just #Autowire ApplicationContext context; in any other spring bean object. With which you can call getBean(YourBean.class) to get that bean.

Elegant way to init or inject string into a static field beforeClass (JUNIT) from spring configuration?

The annotation #Value("${my.field}") work well if you want to inject data into a non static field. In my case, I'm building test for my spring boot application. I'm using Junit. I have some task to do #BeforeClass and I need some properties from spring application configuration. I'm looking for a elegant way to get my properties.
You can load the properties file in the static setup method on your own and select the values needed in your tests. For some, it might be less convenient than injection with #Value, but it will do the trick.
public class SomeTestClass {
private static String myProperty;
#BeforeClass
public static void setUpClass() throws Exception {
Properties prop = new Properties();
prop.load(new FileInputStream("src/main/resources/application.properties"));
myProperty = prop.getProperty("your.property.key");
}
#Test
public void shouldLoadProperty() throws Exception {
assertEquals("expectedValue", myProperty);
}
}

Use spring application as library in non-spring application

I implemented spring-boot application and now I want to use it as a lib for non-spring application.
How can I initialize lib classes so autowired dependencies work as expected?Obviously if I create class instance with 'new', all autowired dependencies will be null.
The theory is that you need to instantiate an application context for your Spring Boot dependency to live in, then extract a bean from there and make use of it.
In practice, in your Spring Boot dependency you should have an Application.java class or similar, in which a main method starts the application. Start by adding there a method like this:
public static ApplicationContext initializeContext(final String[] args) {
return SpringApplication.run(Application.class, args);
}
Next step, in you main application, when you see fit (I'd say during startup but might as well be the first time you need to use your dependency) you need to run this code:
final String[] args = new String[0]; // configure the Spring Boot app as needed
final ApplicationContext context = Application.initializeContext(args); // createSpring application context
final YourBean yourBean = (YourBean)context.getBean("yourBean"); // get a reference of your bean from the application context
From here you can use your beans as you see fit.
I'm not sure how you will handle to wait until the context is fully loaded before you try to access some beans from your Constructor etc. But if you just want to access context without creating components manually try one of those:
1) Simply Inject ApplicationContext
#Inject
private ApplicationContext context;
or
2) Implement ApplicationContextAware
public class ApplicationContext implements ApplicationContextAware {
private ApplicationContext context;
#Override
public void setApplicationContext(ApplicationContext context) {
this.context = context;
}
// just quick example, better to set it to your custom singleton class
public static ApplicationContext getContext() {
return context;
}
}
Then use context.getBean(SomeServiceFromLibrary.class);

how to get beans from application context loaded by contextloaderlistener?

I'm new to Spring/Spring Mvc and here's my problem. In my webapp, besides the spring-servlet.xml , I have a jdbc.xml which define beans like datasource, dao ... Before using contextloaderlistener , I load my jdbc.xml inside the Controller's constructor like this ApplicationContext context = new ClassPathXmlApplicationContext("jdbcbeans.xml") then get the beans from that. But since I'm using contextloaderlistener to load the file, how can I get the reference to the context ? I was able to set up everything using those #Autowired things but I just want to know is there any way to do that ?
You can use WebApplicationContextUtils.
ApplicationContext context;
context = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);
See here for details.
You can do the following to get an instance of Application Context
in case of a container managed bean use ApplicationContextAware interface
public class MyBean implements ApplicationContextAware {
private static ApplicationContext context;
public void setApplicationContext(ApplicationContext acontext) throws BeansException {
context = context;
}
public static ApplicationContext getApplicationContext() {
return context;
}
}
Or you can write the following
#Autowired
private ApplicationContext Context;
An instance of the Application Context will be autowired.

Correct usage subclassing a spring ContextLoader for testing

For the integration tests for my spring application with junit I am subclassing org.springframework.test.context.ContextLoader, because I want to use a already present XmlWebApplicationContext for wiring up my test class like this:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(loader=MyContextLoader.class)
#Transactional
public class MyTest {
#Autowired
public AccountDao accountDao;
}
The implementation of my ContextLoader is as follows:
public class MyContextLoader implements ContextLoader {
#Override
public String[] processLocations(Class<?> clazz, String... locations) {
return locations;
}
#Override
public ApplicationContext loadContext(String... locations) throws Exception {
try {
// Start Embedded Tomcat
EmbeddedTomcat tomcat = new EmbeddedTomcat("mas", 8080);
tomcat.launch();
Context rootContext = tomcat.getRootContext();
ContextLoaderListener contextLoaderListener = (ContextLoaderListener) rootContext.getApplicationLifecycleListeners()[0];
XmlWebApplicationContext context = (XmlWebApplicationContext) contextLoaderListener.getContext();
GenericApplicationContext c = new GenericApplicationContext(context);
AnnotationConfigUtils.registerAnnotationConfigProcessors(c);
//context.refresh();
//context.registerShutdownHook();
return context;
}
catch(Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
When putting a breakpoint in the loadContext(...) method I can call getBean(AccountDao.class) and everything works fine. However, it seems that my test class actually is not autowired. I debugged a little and stepped through the spring code and it seems that in the method AbstractAutowireCapableBeanFactory.populateBean(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw) the PropertyValues are not set for my class Test.
Maybe, am I setting up the Annotation Processing wrong?
Information to the code: As you might guess and see, I am doing an integration test and therefore starting an embedded tomcat server in order to test my RESTful webservice. How getting the application context with a "hack" from an embedded tomcat is shown in my post here: Getting Access to Spring with Embedded Tomcat 6
I am looking forward to your replies.
Erik
I think the problem here is that you're creating a new GenericApplicationContext, which is not the one that Spring uses to autowire the test bean.

Resources