I am trying to write a JavaFX aplication integrated with Spring Boot. It works, but there is some problem with integration test. I want to place MyApplication and Config classes to different packages, so, I add in MyApplication
scanBasePackages = "com.stackoveflow"
and then my test failes with exceptions:
java.lang.IllegalStateException: Failed to load ApplicationContext
Caused by: org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'mainView' defined in class path
resource [com/stackoveflow/core/Config.class]: Bean instantiation via
factory method failed; nested exception is
org.springframework.beans.BeanInstantiationException: Failed to
instantiate [com.stackoveflow.core.View]: Factory method 'getMainView'
threw exception; nested exception is
java.lang.ExceptionInInitializerError Caused by:
java.lang.ExceptionInInitializerError Caused by:
java.lang.IllegalStateException: Toolkit not initialized
if I remove scanBasePackages = "com.stackoveflow"
#Lazy
#SpringBootApplication()
public class MyApplication extends Application {
Test become succesfull, but application itself failes with exception about "cannot find beans" defined in Config.
my code:
MyApplication.java
#Lazy
#SpringBootApplication(scanBasePackages = "com.stackoveflow")
public class MyApplication extends Application {
private static String[] savedArgs;
protected ConfigurableApplicationContext context;
#Override
public void init() throws Exception {
context = SpringApplication.run(getClass(), savedArgs);
context.getAutowireCapableBeanFactory().autowireBean(this);
}
#Override
public void stop() throws Exception {
super.stop();
context.close();
}
protected static void launchApp(Class<? extends Application> clazz, String[] args) {
savedArgs = args;
Application.launch(clazz, args);
}
#Value("${ui.title:JavaFX приложение}")
private String windowTitle;
#Qualifier("mainView")
#Autowired
private View view;
#Override
public void start(Stage stage) throws Exception {
stage.setTitle(windowTitle);
stage.setScene(new Scene(view.getRoot()));
stage.setResizable(true);
stage.centerOnScreen();
stage.show();
}
public static void main(String[] args) {
launchApp(MyApplication.class, args);
}
}
Config.java
#Configuration
public class Config {
#Bean(name = "mainView")
public View getMainView() throws IOException {
return loadView("fxml/main.fxml");
}
#Bean
public Controller getMainController() throws IOException {
return (Controller) getMainView().getController();
}
protected View loadView(String url) throws IOException {
InputStream fxmlStream = null;
try {
fxmlStream = getClass().getClassLoader().getResourceAsStream(url);
FXMLLoader loader = new FXMLLoader();
loader.load(fxmlStream);
return new View(loader.getRoot(), loader.getController());
} finally {
if (fxmlStream != null) {
fxmlStream.close();
}
}
}
}
MyApplicationTest.java
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = MyApplication.class)
public class MyApplicationTests {
#Test
public void contextLoads() {
System.out.println("lol");
}
}
Related
I want to create a bean with the values of string parameters provided in cmd line
#Configuration
public class SpringConfig {
#Bean
public DataProvider getDataProvider(String filePath, String mnhPath) throws Exception {
return new DataProvider(filePath, mnhPath);
}
}
#SpringBootApplication
public class SomeApplication implements CommandLineRunner {
#Autowired
private BeanFactory beanFactory;
public static void main(String[] args) {
SpringApplication.run(SomeApplication .class, args);
}
#Override
public void run(final String... args) throws Exception {
final CommandLineArgs arguments = new CommandLineArgs();
CmdLineParser parser = new CmdLineParser(arguments);
parser.parseArgument(args);
DataProvider dataProvider = beanFactory.getBean(DataProvider.class, arguments.one(), arguments.two());
dataProvider.doSomeOperation();
}
}
But I am getting an error
Description:
Parameter 0 of constructor in com.tomtom.display.height.HeightsDataProvider required a bean of type 'java.lang.String' that could not be found.
Action:
Consider defining a bean of type 'java.lang.String' in your configuration.
How should I correctly configure the bean?
It does not seem to work if you try to create a bean of the format, and attempt at retrieving it.
#Bean
public Bean myBean(String xyz){
return new Bean(xyz);
}
You could bypass this limitation by doing the following:
#Getter
#Setter
#NoArgsConstructor
public class MyBeanExample{
private String hello;
private String world;
}
#SpringBootApplication
public class DemoApplication {
#Bean
public MyBeanExample myBeanExample(){
return new MyBeanExample();
}
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(DemoApplication.class, args);
MyBeanExample beanWithArgs = ctx.getBean(MyBeanExample.class);
beanWithArgs.setHello(args[0]);
beanWithArgs.setWorld(args[1]);
System.out.println(beanWithArgs.getHello());
System.out.println(beanWithArgs.getWorld());
}
}
This would retrieve your #Bean myBeanExample() and then you use setters to set the parameters you need.
I am learning the initialization and destruction callbacks for a bean managed by ApplicationContext in a springboot application. I have a bean which implements InitializingBeans and DisposableBeans interfaces.I do have a #PostConstruct which gets invoked. However I am not seeing the init method invoked when i remove the implementation.What am i missing?
#Component
public class LifeCycleBean implements InitializingBean, DisposableBeans{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public LifeCycleBean() {
// TODO Auto-generated constructor stub
System.out.println("Learning lifecycle - COnstructor invoked"+name);
}
#Override
public void destroy() throws Exception {
System.out.println("Learning lifecycle - Calling Destroy Method");
}
#Override
public void afterPropertiesSet() throws Exception {
// TODO Auto-generated method stub
System.out.println("Learning lifecycle - afterPropertiesSet
invoked"+name);
}
//This never got executed
public void init() {
System.out.println("Learning lifecycle - initMethod invoked"+name);
}
#PostConstruct
public void postConstructMethod() {
System.out.println("Learning lifecycle - postConstructMethod
invoked"+name);
}
#PreDestroy
public void preDestroyMethod() {
System.out.println("Learning lifecycle - preDestroyMethod invoked"+name);
}
}
SpringBootApplication
#SpringBootApplication
public class LifeCycleApplication {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(LifeCycleApplication.class, args);
System.out.println("going to get bean definition names");
ctx.getBeanDefinitionNames();
LifeCycleBean bean = ctx.getBean(LifeCycleBean.class);
System.out.println("before setting name");
bean.setName("bean");
System.out.println("after setting name");
}
}
How and when do i see the init method invoked in springboot application?
I'm trying to use dbunit to test my DAOs. We use Spring in a version that is not compatible with spring-test-dbunit. I can't autowire my dao beans into my test class, because then I would have to use #RunWith(SpringJUnit4ClassRunner.class) which regards one parameterless constructor. My class looks like following:
public class DbUnitExample extends DBTestCase {
#Autowired
public MyDAO myDAO;
public DbUnitExample(String name) {
super(name);
System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_DRIVER_CLASS, "com.mysql.jdbc.Driver");
System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_CONNECTION_URL, "...");
System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_USERNAME, "...");
System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_PASSWORD, "...");
}
#Override
protected IDataSet getDataSet() throws Exception {
return new FlatXmlDataSetBuilder().build(new FileInputStream("target/partial.xml"));
}
#Override
protected DatabaseOperation getSetUpOperation() throws Exception {
return DatabaseOperation.REFRESH;
}
#Override
protected DatabaseOperation getTearDownOperation() throws Exception {
return DatabaseOperation.NONE;
}
#Test
public void testSometing() throws Exception {
myDAO.deleteById(12662);
}
}
Of course I get an NPE because my dao bean can't be found. When I use #RunWith(SpringJUnit4ClassRunner.class) I need to provide one parameterless constructor and have to delete my "dbunit"-constructor. Is there a standard way or workaround to use dbunit with spring without the use of spring-test-dbunit
EDIT
My class now looks like following:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("/test-application.xml")
#DirtiesContext
#TestExecutionListeners({ DependencyInjectionTestExecutionListener.class, DirtiesContextTestExecutionListener.class })
public class DbUnitExample extends DBTestCase {
#Autowired
public MyDAO myDAO;
public DbUnitExample() {
super("target/partial.xml");
System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_DRIVER_CLASS, "com.mysql.jdbc.Driver");
System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_CONNECTION_URL, "...");
System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_USERNAME, "...");
System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_PASSWORD, "...");
}
#Override
protected IDataSet getDataSet() throws Exception {
return new FlatXmlDataSetBuilder().build(new FileInputStream("target/partial.xml"));
}
#Override
protected DatabaseOperation getSetUpOperation() throws Exception {
return DatabaseOperation.REFRESH;
}
#Override
protected DatabaseOperation getTearDownOperation() throws Exception {
// return DatabaseOperation.NONE;
// return DatabaseOperation.REFRESH;
return DatabaseOperation.CLEAN_INSERT;
}
#Test
public void testSometing() throws Exception {
myDAO.deleteById(12662);
}
}
It compiles now, but has no dbunt-functionality, which means if I delete a row it doesn't get restored to it's previous state (inserted again).
Since you are using Spring, I suggest autowiring the dbUnit instances into the test. The dbUnit Test Cases page has "Configuration Example Using Spring" for the PrepAndExpectedTestCase, but just copy the code and change it to DBTestCase and adjust accordingly.
I have strange situation with #Autowired
App's main class:
#Configuration
#EnableAutoConfiguration
#SpringBootApplication
#ComponentScan({"khartn", "khartn.torrentsuploader.processor"})
public class NewMain implements CommandLineRunner {
public static void main(String[] args) {
SpringApplicationBuilder builder = new SpringApplicationBuilder(NewMain.class);
builder.headless(false);
ConfigurableApplicationContext context = builder.run(args);
}
#Override
public void run(String... args) throws Exception {
}
}
Component class:
#Component("MyDirectoryReader")
public class MyDirectoryReader {
public MyDirectoryReader ( ) {
System.out.println("qqqqqqqqqqqqqqq");
}
public void readDir() {
try {
String initialPathStr = NewJFrame.jTextField1.getText();
System.out.println("initialPathStr " + initialPathStr);
Path dir = FileSystems.getDefault().getPath(initialPathStr);
DirectoryStream<Path> stream = Files.newDirectoryStream(dir, "*.{torrent}");
for (Path path : stream) {
System.out.println(path.getFileName());
}
stream.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
When application starting, I see, what MyDirectoryReader class is initialized:
2015-04-11 21:42:29.405 INFO 9375 --- [.NewMain.main()] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext#13d6044f: startup date [Sat Apr 11 21:42:29 SAMT 2015]; root of context hierarchy
qqqqqqqqqqqqqqq
Config class:
#Configuration
#ComponentScan({"khartn", "khartn.torrentsuploader.processor"})
public class AppConfig {
#Bean(initMethod = "init")
public NewJFrame mainForm() {
System.out.println("init mainForm");
return new NewJFrame();
}
}
And in NewJFrame class have autowired field
public class NewJFrame extends javax.swing.JFrame {
#Autowired
#Qualifier(value = "MyDirectoryReader")
MyDirectoryReader myDirectoryReader;
But when NewJFrame showed and button pressed,
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
if (myDirectoryReader == null) {
System.out.println("myDirectoryReader is null");
}
// myDirectoryReader.readDir();
}
then myDirectoryReader is null.
Why MyDirectoryReader is initialized as Component, but not autowired to the field?
According to the code from the init method, you make the call new NewJFrame().setVisible(true);, however, when you create an object yourself, Spring doesn't know that and autowiring doesn't work. You have to use the Spring bean object itself. I think, if you change that line to this.setVisible(true), it should work correctly (since the init method is executed when the bean is instantiated).
I am trying to create test cases in my application using powermock and TestNG. This is a web application and spring context xml is loaded through web.xml. I want to mock the spring context xml with my own test xml and access beans from there.
ContextLoader Code
public class AppContextLoader implements ApplicationContextAware {
private static ApplicationContext context;
public void setApplicationContext(ApplicationContext context) {
this.context = context;
}
public static Object getBean(String beanName) {
return context.getBean(beanName);
}
}
I am trying to access a bean later in my code like below
XMLConverter converter = (XMLConverter) AppContextLoader.getBean("XMLConverter");
Below is my Test Code
#PrepareForTest(AppContextLoader.class)
#PowerMockIgnore({"javax.management.*", "javax.xml.*","org.xml.*","org.w3c.dom.*"})
public class ImplTest {
Impl impl;
ApplicationContext context;
#ObjectFactory
/**
* Configure TestNG to use the PowerMock object factory.
*/
public IObjectFactory getObjectFactory() {
return new org.powermock.modules.testng.PowerMockObjectFactory();
}
#BeforeClass
public void setUp() throws Exception {
impl = new Impl();
context = new ClassPathXmlApplicationContext("Test_config.xml");
}
#Test
public void execute() {
try {
PowerMock.mockStatic(AppContextLoader.class);
expect(AppContextLoader.getBean("XMLConverter")).andReturn(context.getBean("XMLConverter"));
PowerMock.replay(AppContextLoader.class);
actualResponse = impl.execute(request, "");
//PowerMock.verify(AppContextLoader.class);
Assert.assertEquals("", actualResponse);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
When I am executing this code I am getting below error:
java.lang.ClassCastException: com.xxx.xxx.xxx.xxx.bean.XMLConverter cannot be cast to com.xxx.xxx.xxx.xxx.bean.XMLConverter
I am new to unit testing, and not sure what is causing this issue where same class are not able to cast each other. Any help will be appreciated