I am new to springs. I am trying to call init and destroy method for different bean invoking
My init method is called from only "FileSystemResource" Why it was not called from others?
public class DefaultMessage {
private String message = "Basic Bean injecting";
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public DefaultMessage(String message) {
this.message = message;
}
public DefaultMessage() {
}
public void init(){
System.out.println("Testing init.");
}
public void destory(){
System.out.println("Spring Container is destroyed.");
}
My XML is
<bean id="basicBean" class="com.sarma.spring.core.DefaultMessage" init-method="init" destroy-method="destory"></bean>
Main class
//Type 1
ApplicationContext applicationContext =new ClassPathXmlApplicationContext("DefaultMessage.xml");
//Basic Bean Testing
DefaultMessage message = (DefaultMessage) applicationContext.getBean("basicBean");
log.info(message.getMessage());
log.info("---------------------------ApplicationContext End------------------------------");
//Type 2
Resource res = new FileSystemResource("C:\\Sarma\\Spring\\SpringEx\\src\\resource\\DefaultMessage.xml");
BeanFactory factory = new XmlBeanFactory(res);
DefaultMessage message1 = (DefaultMessage) factory.getBean("basicBean");
log.info("Test "+message1.getMessage());
log.info("- ---------------------------FileSystemResource End------------------------------");
//Type 3
ClassPathResource res1 = new ClassPathResource("DefaultMessage.xml");
BeanFactory factory1 = new XmlBeanFactory(res1);
DefaultMessage message2 = (DefaultMessage) factory1.getBean("basicBean");
log.info("Test "+message2.getMessage());
log.info("- ---------------------------ClassPathResource End-------------------------------");
//Type4
ConfigurableApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"DefaultMessage.xml"});
DefaultMessage message3 = (DefaultMessage) context.getBean("basicBean");
log.info(message3.getMessage());
context.close();
log.info("- ---------------------------ConfigurableApplicationContext End------------------");
OUTPUT
2013-09-18 13:49:22 INFO ClassPathXmlApplicationContext:513 - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext#913750: startup date [Wed Sep 18 13:49:22 EDT 2013]; root of context hierarchy
2013-09-18 13:49:22 INFO XmlBeanDefinitionReader:316 - Loading XML bean definitions from class path resource [DefaultMessage.xml]
2013-09-18 13:49:22 INFO DefaultMessageMain:27 - Basic Bean injecting
2013-09-18 13:49:22 INFO DefaultMessageMain:29 - ---------------------------ApplicationContext End------------------------------
2013-09-18 13:49:22 INFO XmlBeanDefinitionReader:316 - Loading XML bean definitions from file [C:\Sarma\Spring\SpringEx\src\resource\DefaultMessage.xml]
Testing init.
2013-09-18 13:49:22 INFO DefaultMessageMain:36 - Test Basic Bean injecting
2013-09-18 13:49:22 INFO DefaultMessageMain:37 - - ---------------------------FileSystemResource End------------------------------
2013-09-18 13:49:22 INFO XmlBeanDefinitionReader:316 - Loading XML bean definitions from class path resource [DefaultMessage.xml]
2013-09-18 13:49:22 INFO DefaultMessageMain:42 - Test Basic Bean injecting
2013-09-18 13:49:22 INFO DefaultMessageMain:43 - - ---------------------------ClassPathResource End-------------------------------
2013-09-18 13:49:22 INFO ClassPathXmlApplicationContext:513 - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext#176e552: startup date [Wed Sep 18 13:49:22 EDT 2013]; root of context hierarchy
2013-09-18 13:49:22 INFO XmlBeanDefinitionReader:316 - Loading XML bean definitions from class path resource [DefaultMessage.xml]
2013-09-18 13:49:22 INFO DefaultMessageMain:47 - Basic Bean injecting
2013-09-18 13:49:22 INFO ClassPathXmlApplicationContext:873 - Closing org.springframework.context.support.ClassPathXmlApplicationContext#176e552: startup date [Wed Sep 18 13:49:22 EDT 2013]; root of context hierarchy
2013-09-18 13:49:22 INFO DefaultMessageMain:49 - - ---------------------------ConfigurableApplicationContext End------------------
My init method is called from only "FileSystemResource" Why it was not called from others?
Why it is behaving different?
It never called my destroy method
I'm going to copy your code to explain
//Type 1
ApplicationContext applicationContext =new ClassPathXmlApplicationContext("DefaultMessage.xml");
//Basic Bean Testing
DefaultMessage message = (DefaultMessage) applicationContext.getBean("basicBean");
The above will init() your bean.
//Type 2
Resource res = new FileSystemResource("C:\\Sarma\\Spring\\SpringEx\\src\\resource\\DefaultMessage.xml");
BeanFactory factory = new XmlBeanFactory(res);
DefaultMessage message1 = (DefaultMessage) factory.getBean("basicBean");
This will also init() your bean.
//Type 3
ClassPathResource res1 = new ClassPathResource("DefaultMessage.xml");
BeanFactory factory1 = new XmlBeanFactory(res1);
DefaultMessage message2 = (DefaultMessage) factory1.getBean("basicBean");
This will also init() your bean.
//Type4
ConfigurableApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"DefaultMessage.xml"});
DefaultMessage message3 = (DefaultMessage) context.getBean("basicBean");
log.info(message3.getMessage());
context.close();
This will also init() your bean. Because of the context.close(), all beans will be destroyed before the context being closed. If the destroy-method isn't being called, you can try with DisposableBean interface, but consider that bad practice as your classes start being dependent on Spring types.
I have implemented DisposableBean interface to my bean class and overrides destroy method and removed destroy-method method form my XML.
Now destroy method is calling 3 times except ApplicationContext,
Destroy method is calling from FileSystemResource, ClassPathResource, ClassPathXmlApplicationContext and not from ApplicationContext.
For ClassPathXmlApplicationContext, we can pass different xml's for example
ConfigurableApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"DefaultMessage.xml", "DefaultMessage1.xml}");
while closing ConfigurableApplicationContext it will close all resource which was opened, that why it closed all 3 FileSystemResource, ClassPathResource, ClassPathXmlApplicationContext.
Related
I am playing around with Weld CDI configuration. I got stuck with NULL being returned. Theoritically my configuration should make proper object instance created but I can't find reason it doesn't...
I looked up for similar questions, but most issues were related to use of new keyword while instantating the object. The other advise is to use application server. I'm running wildfly, so it's not the case as well.
Log:
Feb 17, 2021 12:12:18 AM org.jboss.weld.bootstrap.WeldStartup <clinit>
INFO: WELD-000900: 4.0.0 (Final)
Feb 17, 2021 12:12:19 AM org.jboss.weld.bootstrap.WeldStartup startContainer
INFO: WELD-000101: Transactional services not available. Injection of #Inject UserTransaction not available. Transactional observers will be invoked synchronously.
Feb 17, 2021 12:12:19 AM org.jboss.weld.environment.se.WeldContainer fireContainerInitializedEvent
INFO: WELD-ENV-002003: Weld SE container 75c04868-bd06-4acb-874c-db603ada27b0 initialized
Exception in thread "main" java.lang.NullPointerException
at MessagePrinter.printMessage(MessagePrinter.java:9)
at Main.main(Main.java:10)
Weld SE container 75c04868-bd06-4acb-874c-db603ada27b0 shut down by shutdown hook
Process finished with exit code 1
Here's my setup:
beans.xml simple as can be
<?xml version="1.0"?>
<beans bean-discovery-mode="all" version="1.1"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"/>
Main class - creating Weld container
import org.jboss.weld.environment.se.Weld;
import org.jboss.weld.environment.se.WeldContainer;
public class Main {
public static void main(String[] args) {
Weld weld = new Weld();
WeldContainer container = weld.initialize();
MessagePrinter printer = container.select(MessagePrinter.class).get();
printer.printMessage();
weld.shutdown();
}
}
MessagePrinter class
import javax.inject.Inject;
public class MessagePrinter {
#Inject
private MessageProducer messageProducer;
public void printMessage() {
String message = messageProducer.getMessage();
System.out.println(message);
}
}
So above MessageProducer variable is always null although one only existing MessageProducer implementation (mark as #default) should be injected...
MessageProducer interface
public interface MessageProducer {
public String getMessage();
}
SimpleMessageProducer class (MessageProducer implementation)
import javax.enterprise.inject.Any;
import javax.enterprise.inject.Default;
#Default
#Any
public class SimpleMessageProducer implements MessageProducer {
#Override
public String getMessage() {
return "Example message " + System.currentTimeMillis();
}
}
Project structure:
-src
--java
---FileMessage
---FileMessageProducer
---Main
---MessagePrinter
---MessageProducer
---SimpleMessageProducer
-resources
--META-INF
---beans.xml
As you are using Weld 4.0.0.Final, you should use jakarta.inject namespace instead of javax.inject.
You probably are having issues due overlapping classpaths. Keep only the org.jboss.weld.se:weld-se-core:4.0.0.Final dependency and you will probably be fine.
I am developing a demo spring boot app in which it is possible to configure 3 different database with a DDBBconfig class by usisng application.properties of the aplication.
The class iis the following:
#Configuration
public class DDBBConfig {
//Flags Configuration
#Value("${DDBB.postgresql}")
private Boolean postgresql;
#Value("${DDBB.mysql}")
private Boolean mysql;
#Value("${DDBB.h2}")
private Boolean h2;
//Datasource Configuration parameters
#Value("${mysql.datasource.driver-class-name}")
private String driverMysql;
#Value("${mysql.datasource.url}")
private String urlMysql;
#Value("${mysql.datasource.username}")
private String usernameMysql;
#Value("${mysql.datasource.password}")
private String passwordMysql;
#Value("${postgresql.datasource.driver-class-name}")
private String driverPostgresql;
#Value("${postgresql.datasource.url}")
private String urlPostgresql;
#Value("${postgresql.datasource.username}")
private String usernamePostgresql;
#Value("${postgresql.datasource.password}")
private String passwordPostgresql;
#Value("${spring.datasource.driverClassName}")
private String driverH2;
#Value("${spring.datasource.url}")
private String urlH2;
#Value("${spring.datasource.username}")
private String usernameH2;
#Value("${spring.datasource.password}")
private String passwordH2;
#Bean
public DataSource getDataSource() {
DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create();
validateOnlyOneFlag( postgresql, mysql, h2 );
if (Boolean.TRUE.equals( mysql )) {
dataSourceBuilder.driverClassName( driverMysql );
dataSourceBuilder.url( urlMysql );
dataSourceBuilder.username( usernameMysql );
dataSourceBuilder.password( passwordMysql );
} else if (Boolean.TRUE.equals( postgresql )) {
dataSourceBuilder.driverClassName( driverPostgresql );
dataSourceBuilder.url( urlPostgresql );
dataSourceBuilder.username( usernamePostgresql );
dataSourceBuilder.password( passwordPostgresql );
} else if (Boolean.TRUE.equals( h2 )) {
dataSourceBuilder.driverClassName( driverH2 );
dataSourceBuilder.url( urlH2 );
dataSourceBuilder.username( usernameH2 );
dataSourceBuilder.password( passwordH2 );
}
return dataSourceBuilder.build();
}
public void validateOnlyOneFlag(Boolean postgress, Boolean mySql, Boolean h2) {
Integer flagsTrue = 0;
if (postgress) {
flagsTrue++;
}
if (mySql) {
flagsTrue++;
}
if (h2) {
flagsTrue++;
}
if (flagsTrue > 1) {
throw new IllegalArgumentException( "There is more than One database Flags to True." + "\n\tDDBB.postgresql=" + postgress +
"\n\tDDBB.mysql=" + mySql + "\n\tDDBB.h2=" + h2 );
} else if (flagsTrue == 0) {
throw new IllegalArgumentException( "\n\n\tDatabase flags are all false, please set at least one flag to true" );
}
}
}
Then in the application.properties I have somo flags and the configuration parameters.
#BBDD:
DDBB.postgresql=true
DDBB.mysql=false
DDBB.h2=false
#JPA:
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
#Properties mysql
mysql.datasource.url=jdbc:mysql://localhost:3306/myapp?serverTimezone=UTC
mysql.datasource.username=root
mysql.datasource.password=AdminPass123
mysql.datasource.driver-class-name=com.mysql.jdbc.Driver
#Properties postgresql
postgresql.datasource.url=jdbc:postgresql://localhost/petapp
postgresql.datasource.username=postgres
postgresql.datasource.password=1234
postgresql.datasource.driver-class-name=org.postgresql.Driver
#Properties H2
h2.datasource.url=jdbc:h2:mem:petappDB
h2.datasource.username=sa
h2.datasource.password=password
h2.datasource.driverClassName=org.h2.Driver
spring.h2.console.enabled=${DDBB.h2}
Its works perfect so I can configure 3 databases.
Then I also have a DataBase initialization class that add some initial data for initialization and front developing reasons. It initialize the roles, creates a default admin user for login and so on.
#Component
public class DDBBInitializer {
private static final Logger log = LoggerFactory.getLogger( DDBBInitializer.class );
#Autowired
private RoleRepository roleRepository;
#Autowired
private UserRepository userRepository;
#Autowired
private OwnerRepository ownerRepository;
#Autowired
private PetRepository petRepository;
#Autowired
private PasswordEncoder passwordEncoder;
#Value("${pettapp.config.default.username}")
private String defaultUsername;
#Value("${pettapp.config.default.email}")
private String defaultEmail;
#Value("${pettapp.config.default.password}")
private String defaultPassword;
#PostConstruct
private void init() {
log.info( "Initializacion of the DDBB" );
for (Roles role : Roles.values()) {
Role roleEntity = new Role( role );
roleRepository.save( roleEntity );
log.info( "Role: " + roleEntity.getRoleName() + " stored on DDBB" );
}
User defaultAdminUser = new User();
defaultAdminUser.setUserId( new BigDecimal( 1 ) );
defaultAdminUser.addOneRole( Roles.ADMIN );
defaultAdminUser.setUsername( defaultUsername );
defaultAdminUser.setPassword( passwordEncoder.encode( defaultPassword ) );
defaultAdminUser.setActive( true );
defaultAdminUser.setEmail( defaultEmail );
log.info( "Default AdminUser Created: " + defaultAdminUser.getUsername() + "/" + defaultPassword );
Owner adminOwnerProfile = new Owner();
adminOwnerProfile.setAddress( "Calle de jacinto NÂș6 Bajo B" );
adminOwnerProfile.setName( "Manolo" );
adminOwnerProfile.setSurname( "Amelgas" );
adminOwnerProfile.setDefaulter( false );
adminOwnerProfile.setTelephoneNumber( "678987656 " );
adminOwnerProfile.setUser( defaultAdminUser );
defaultAdminUser.setOwner( adminOwnerProfile );
log.info( "Default Owner Created: " + adminOwnerProfile.getName() + " " + adminOwnerProfile.getSurname() );
Pet testPet = new Pet();
testPet.setAlive( true );
testPet.setBitrh( new Date() );
testPet.setBreed( "Carlino" );
testPet.setFur( "White" );
testPet.setName( "Lucky" );
testPet.setOwner( adminOwnerProfile );
adminOwnerProfile.addPet( testPet );
log.info( "Default Pet Created: " + testPet.getName() );
userRepository.save( defaultAdminUser );
}
}
Now I want to create all Test with Junit for all methods that I have in my application (currently i have like 10 controllers, 15 services and 30 different methods to Test)
I would like to configure the test to always use an H2 database and load some initial data and i cant find good documentation about it. How i should proccedd to load initial data as i do for the app but only for the test?.
I have created a /test/resources/application-test.properties with the same parameters as in /java/resources/application.properties but configuring H2 (Its means that H" flag is set to true).
DDBB.postgresql=false
DDBB.mysql=false
DDBB.h2=true
When compiling the application it is still using for test the application.properties files as it can be seen in logs:
[INFO] -------------------------------------------------------
[INFO] T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.mashosoft.backEndTest.BackEndTestApplicationTests
[INFO] -------------------------------------------------------
[INFO] T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.mashosoft.backEndTest.BackEndTestApplicationTests
12:01:02.759 [main] DEBUG org.springframework.test.context.junit4.SpringJUnit4ClassRunner - SpringJUnit4ClassRunner constructor called with [class com.mashosoft.backEndTest.BackEndTestApplicationTests]
12:01:02.768 [main] DEBUG org.springframework.test.context.BootstrapUtils - Instantiating CacheAwareContextLoaderDelegate from class [org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate]
12:01:02.783 [main] DEBUG org.springframework.test.context.BootstrapUtils - Instantiating BootstrapContext using constructor [public org.springframework.test.context.support.DefaultBootstrapContext(java.lang.Class,org.springframework.test.context.CacheAwareContextLoaderDelegate)]
12:01:02.824 [main] DEBUG org.springframework.test.context.BootstrapUtils - Instantiating TestContextBootstrapper for test class [com.mashosoft.backEndTest.BackEndTestApplicationTests] from class [org.springframework.boot.test.context.SpringBootTestContextBootstrapper]
12:01:02.864 [main] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Neither #ContextConfiguration nor #ContextHierarchy found for test class [com.mashosoft.backEndTest.BackEndTestApplicationTests], using SpringBootContextLoader
12:01:02.869 [main] DEBUG org.springframework.test.context.support.AbstractContextLoader - Did not detect default resource location for test class [com.mashosoft.backEndTest.BackEndTestApplicationTests]: class path resource [com/mashosoft/backEndTest/BackEndTestApplicationTests-context.xml] does not exist
12:01:02.870 [main] DEBUG org.springframework.test.context.support.AbstractContextLoader - Did not detect default resource location for test class [com.mashosoft.backEndTest.BackEndTestApplicationTests]: class path resource [com/mashosoft/backEndTest/BackEndTestApplicationTestsContext.groovy] does not exist
12:01:02.870 [main] INFO org.springframework.test.context.support.AbstractContextLoader - Could not detect default resource locations for test class [com.mashosoft.backEndTest.BackEndTestApplicationTests]: no resource found for suffixes {-context.xml, Context.groovy}.
12:01:02.872 [main] INFO org.springframework.test.context.support.AnnotationConfigContextLoaderUtils - Could not detect default configuration classes for test class [com.mashosoft.backEndTest.BackEndTestApplicationTests]: BackEndTestApplicationTests does not declare any static, non-private, non-final, nested classes annotated with #Configuration.
12:01:02.961 [main] DEBUG org.springframework.test.context.support.ActiveProfilesUtils - Could not find an 'annotation declaring class' for annotation type [org.springframework.test.context.ActiveProfiles] and class [com.mashosoft.backEndTest.BackEndTestApplicationTests]
12:01:03.068 [main] DEBUG org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider - Identified candidate component class: file [D:\Proyectos\PetApp\Back\target\classes\com\mashosoft\backEndTest\BackEndTestApplication.class]
12:01:03.084 [main] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Found #SpringBootConfiguration com.mashosoft.backEndTest.BackEndTestApplication for test class com.mashosoft.backEndTest.BackEndTestApplicationTests
12:01:03.203 [main] DEBUG org.springframework.boot.test.context.SpringBootTestContextBootstrapper - #TestExecutionListeners is not present for class [com.mashosoft.backEndTest.BackEndTestApplicationTests]: using defaults.
12:01:03.203 [main] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Loaded default TestExecutionListener class names from location [META-INF/spring.factories]: [org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener, org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener, org.springframework.boot.test.autoconfigure.restdocs.RestDocsTestExecutionListener, org.springframework.boot.test.autoconfigure.web.client.MockRestServiceServerResetTestExecutionListener, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcPrintOnlyOnFailureTestExecutionListener, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverTestExecutionListener, org.springframework.security.test.context.support.WithSecurityContextTestExecutionListener, org.springframework.security.test.context.support.ReactorContextTestExecutionListener, org.springframework.test.context.web.ServletTestExecutionListener, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener, org.springframework.test.context.support.DependencyInjectionTestExecutionListener, org.springframework.test.context.support.DirtiesContextTestExecutionListener, org.springframework.test.context.transaction.TransactionalTestExecutionListener, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener]
12:01:03.223 [main] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Using TestExecutionListeners: [org.springframework.test.context.web.ServletTestExecutionListener#7d20d0b, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener#77f1baf5, org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener#41a2befb, org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener#6c40365c, org.springframework.test.context.support.DirtiesContextTestExecutionListener#7bedc48a, org.springframework.test.context.transaction.TransactionalTestExecutionListener#131ef10, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener#55b0dcab, org.springframework.security.test.context.support.WithSecurityContextTestExecutionListener#38afe297, org.springframework.security.test.context.support.ReactorContextTestExecutionListener#2df3b89c, org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener#23348b5d, org.springframework.boot.test.autoconfigure.restdocs.RestDocsTestExecutionListener#70325e14, org.springframework.boot.test.autoconfigure.web.client.MockRestServiceServerResetTestExecutionListener#37ceb1df, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcPrintOnlyOnFailureTestExecutionListener#7c9d8e2, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverTestExecutionListener#20d525]
12:01:03.223 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved #ProfileValueSourceConfiguration [null] for test class [com.mashosoft.backEndTest.BackEndTestApplicationTests]
12:01:03.223 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved ProfileValueSource type [class org.springframework.test.annotation.SystemProfileValueSource] for class [com.mashosoft.backEndTest.BackEndTestApplicationTests]
12:01:03.223 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved #ProfileValueSourceConfiguration [null] for test class [com.mashosoft.backEndTest.BackEndTestApplicationTests]
12:01:03.223 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved ProfileValueSource type [class org.springframework.test.annotation.SystemProfileValueSource] for class [com.mashosoft.backEndTest.BackEndTestApplicationTests]
12:01:03.223 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved #ProfileValueSourceConfiguration [null] for test class [com.mashosoft.backEndTest.BackEndTestApplicationTests]
12:01:03.223 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved ProfileValueSource type [class org.springframework.test.annotation.SystemProfileValueSource] for class [com.mashosoft.backEndTest.BackEndTestApplicationTests]
12:01:03.239 [main] DEBUG org.springframework.test.context.support.AbstractDirtiesContextTestExecutionListener - Before test class: context [DefaultTestContext#75db5df9 testClass = BackEndTestApplicationTests, testInstance = [null], testMethod = [null], testException = [null], mergedContextConfiguration = [WebMergedContextConfiguration#707194ba testClass = BackEndTestApplicationTests, locations = '{}', classes = '{class com.mashosoft.backEndTest.BackEndTestApplication}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer#b9afc07, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer#80169cf, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer#0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer#6c9f5c0d, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer#0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer#1ee807c6], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map['org.springframework.test.context.web.ServletTestExecutionListener.activateListener' -> true]], class annotated with #DirtiesContext [false] with mode [null].
12:01:03.239 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved #ProfileValueSourceConfiguration [null] for test class [com.mashosoft.backEndTest.BackEndTestApplicationTests]
12:01:03.239 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved ProfileValueSource type [class org.springframework.test.annotation.SystemProfileValueSource] for class [com.mashosoft.backEndTest.BackEndTestApplicationTests]
12:01:03.270 [main] DEBUG org.springframework.test.context.support.TestPropertySourceUtils - Adding inlined properties to environment: {spring.jmx.enabled=false, org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true, server.port=-1}
###########################################################
MyAPP BANNER
###########################################################
2019-10-16 12:01:04,040 INFO [main] org.springframework.boot.StartupInfoLogger: Starting BackEndTestApplicationTests on gggarrido10 with PID 5252 (started by gggarrido in D:\Proyectos\PetApp\Back)
2019-10-16 12:01:04,040 DEBUG [main] org.springframework.boot.StartupInfoLogger: Running with Spring Boot v2.1.6.RELEASE, Spring v5.1.8.RELEASE
2019-10-16 12:01:04,040 INFO [main] org.springframework.boot.SpringApplication: No active profile set, falling back to default profiles: default
2019-10-16 12:01:07,437 INFO [main] com.mashosoft.backEndTest.config.DDBB.DDBBConfig: POSTGRESQL DDBB selected
As it can be seen, for test is still configuring postgresql instead of H2
I have now idea about how to proceed
all the help you can give me would be appreciated.
If I understand your question correctly, you are asking whether your DDBBConfig class when used in test (either as a bean or initialized as a local variable) will use application-test.properties or application.properties. The answer is it will use application-test.properties.
It is important to know that application-test.properties will totally replace application.properties. You can't define only modified delta in your application-test.properties - you have to duplicate the original file and modify it.
Your test should look like the following:
package your.package;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import what.ever.you.need;
#RunWith(SpringRunner.class)
#SpringBootTest
public class YourServiceTestClassName {
#Autowired
private DDBBConfig config;
#Autowired
private DDBBInitializer initializer;
#Test
public void testWhatYouNeed() {
DateSource ds;
ds = config.getDateSource();
// do whatever you need
}
How to make Java ServiceActivator visible in JUnit Test?
I have started writing a test which imports some spring integration xmls via some Java Config files (ie, files set in the #ContextConfiguration). One of these xml files references a channel called pollerErrorChannel this is the input-channel to a ServiceActivator declared in a Java Class. When the test cranks up I get the following error:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sftpInboundAdapterBusiness': Cannot create inner bean '(inner bean)#1fe8d51b' of type [org.springframework.integration.scheduling.PollerMetadata] while setting bean property 'pollerMetadata'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)#1fe8d51b': Cannot create inner bean '(inner bean)#324dcd31' of type [org.springframework.integration.channel.MessagePublishingErrorHandler] while setting bean property 'errorHandler'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)#324dcd31': Cannot resolve reference to bean 'pollerErrorChannel' while setting bean property 'defaultErrorChannel'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'pollerErrorChannel' available
Below in my test
#RunWith(SpringRunner.class)
#ContextConfiguration(classes = {PropertySourcesPlaceholderConfigurer.class,
SFTPSampleReceiver.class,
SampleIngestBusinessConfig.class,
SampleIngestConfig.class,
SessionFactoryConfig.class},
initializers = ConfigFileApplicationContextInitializer.class)
#TestPropertySource(locations={"/application.yml"})
public class BusinessSampleRecieverTests {
#Test
public void test() {
}
}
Segment from sample-ingest-business.xml which specifies pollerErrorChannel as a channel
<int-sftp:inbound-channel-adapter id="sftpInboundAdapterBusiness"
channel="sftpInboundBusiness"
session-factory="sftpSessionFactory"
local-directory="${sftp.localdirectory}/business-local"
filter="businessCompositeFilter"
remote-file-separator="/"
remote-directory="${sftp.directory}/business-sftp">
<int:poller cron="${sftp.cron}" max-messages-per-poll="1" error-channel="pollerErrorChannel"/>
</int-sftp:inbound-channel-adapter>
Here is The Java Class which specifies pollerErrorChannel as the InputChannel to a #ServiceActivator
#Slf4j
#MessageEndpoint
#Component
public class SFTPSampleReceiver {
#ServiceActivator(inputChannel = "pollerErrorChannel", outputChannel = "errorUploadChannel")
public Message<String> processInvalidSample(GenericMessage errorMessage) {
String error = ((Exception) errorMessage.getPayload()).getCause().toString();
String fileName = ((MessagingException) errorMessage.getPayload()).getFailedMessage().getHeaders()
.get("file_name").toString();
String directory = ((MessagingException) errorMessage.getPayload()).getFailedMessage().getHeaders()
.get("sample_type").toString() + "-sftp";
String shortFileName = fileName.replace(".xml", "");
String errorFile = shortFileName + "_error.txt";
log.debug(fileName + " Was invalid and rejected.");
final Message<String> message = MessageBuilder.withPayload(error).setHeader("error_file_name",
errorFile).setHeader("file_name", fileName).setHeader("short_file_name",
shortFileName).setHeader("directory", directory).build();
return message;
}
}
thanks
You have to declare that pollerErrorChannel bean.
With just a #ServiceActivator(inputChannel = "pollerErrorChannel" it will be already to late to have that channel auto-created. The <poller> is parsed and populated as a bean a bit earlier.
We might review the PollerParser to use MessagePublishingErrorHandler.setDefaultErrorChannelName() isntead of errorHandler.addPropertyReference("defaultErrorChannel", errorChannel); to let to resolve the channel late on demand.
Feel free to raise a JIRA on the matter!
Garys comment about adding < int:annotation-config/> to your XML worked
Getting error while running spring program. My program is like below:
And my program to read the xml file :
public static void main(String[] args) {
//String springConfig = "src/main/resources/config/FacebookSimulator.xml";
//String springConfig = "/root/fbdata/FacebookSimulator.xml";
String springConfig = "/config/FacebookSimulator.xml";
//ApplicationContext context = new FileSystemXmlApplicationContext(springConfig);
ApplicationContext context = new ClassPathXmlApplicationContext(springConfig);
JobLauncher jobLauncher = (JobLauncher) context.getBean("jobLauncher");
Job job = (Job) context.getBean("simulatorJob");
This works perfectly in windows.But while running in linux it is showing error like below:
org.springframework.beans.factory.BeanDefinitionStoreException: Unexpected exception parsing XML document from class path resource [config/FaceBookSimulator.xml]; nested exception is org.springframework.beans.FatalBeanException: Class [org.springframework.batch.core.configuration.xml.CoreNamespaceHandler] for namespace [http://www.springframework.org/schema/batch] does not implement the [org.springframework.beans.factory.xml.NamespaceHandler] interface
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:414)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:336)
My question is where exactly should I place facebook.xml in linux system.
i made this as a jar and running in linux
I've inherited some Java code. Several classes have their instance variables initialized from property values in /WEB-INF/servlet.properties like this:
#Value("${context.root}")
private String contextRoot;
When I try this in a new class, the instance variable is not initialized. My class is constructed similarly to the one that works, but it is in a different package (com.company.app.utilities vs. com.company.app.service) Both import the same class:
import org.springframework.beans.factory.annotation.Value;
Both have corresponding public getter and setter methods.
I've reviewed some Spring documentation and /WEB-INF/applicationContext.xml, but I don't see anything obvious that I need to configure.
Any assistance is greatly appreciated.
Update:
I see the following entries in the log:
[localhost-startStop-1] 03 Dec 2014 02:47:10,791 INFO : org.springframework.context.support.PropertySourcesPlaceholderConfigurer - Loading properties file from ServletContext resource [/WEB-INF/servlet.properties]
[localhost-startStop-1] 03 Dec 2014 02:47:10,938 INFO : org.springframework.beans.factory.support.DefaultListableBeanFactory - Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory#601e8f7d: defining beans [...,contactServiceImpl,s3Transfer,...]; parent: org.springframework.beans.factory.support.DefaultListableBeanFactory#32f5f812
I've omitted all other singletons from the log entry, to highlight that both the original class and my class are in the list; however, I created a constructor, whereas the original class has no constructor. The next line in the log is the exception I throw in a getter method when the value is null, caught inside the constructor:
[localhost-startStop-1] 03 Dec 2014 02:47:12,730 ERROR: com.company.app.utilities.S3Transfer - bucketName is null!
java.lang.Exception: bucketName is null!
at com.company.app.utilities.S3Transfer.getBucketName(S3Transfer.java:129)
at com.company.app.utilities.S3Transfer.<init>(S3Transfer.java:48)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:148)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:87)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1000)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:953)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:487)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:626)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479)
at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:651)
at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:599)
at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:665)
at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:518)
at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:459)
at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:136)
at javax.servlet.GenericServlet.init(GenericServlet.java:160)
...
Should I remove the constructor? If so, is there additional Spring configuration to instantiate a singleton of this class? Thanks.
Update 2014-12-03:
I think I've been away from Java too long, as the last time I coded AOP, there was no Spring Framework, and it's got me a bit confused. When you say "instantiated by Spring", does this mean to place #Autowired in the class that uses my new class? I've made this change and I've rewritten my class to implement an interface, but now Tomcat fails to restart properly. Code, properties and logs below:
package com.company.app.utilities;
import com.company.app.bean.Contact;
import java.io.InputStream;
public interface S3Transfer {
String storeContactProfilePicture(Long idUser, Contact contact);
String storeContactProfilePicture(Long idUser, Long idContact, InputStream inStream);
String storeUserProfilePicture(Long idUser, String fileName, String accountType);
}
package com.company.app.utilities;
import com.amazonaws.AmazonClientException;
import com.amazonaws.AmazonServiceException;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.PutObjectRequest;
import com.company.app.bean.Contact;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Value;
public class S3TransferImpl implements S3Transfer {
private final AmazonS3 s3client = new AmazonS3Client();
private final Logger logger = Logger.getLogger(getClass());
#Value("${context.root}")
private String contextRoot;
#Value("${s3.bucket.name}")
private String bucketName;
#Value("${contact.profile.picture}")
private String contactProfilePictureKey;
#Value("${user.profile.picture}")
private String userPictureKey;
public String storeContactProfilePicture(Long idUser, Contact contact) {
String keyName = getContactProfilePictureKey().replaceAll("<<idUsr>>", idUser.toString()).replaceAll("<<idContact>>", contact.getIdContact().toString());
String fileName = contact.getPicture();
storeObjectFromFileName(fileName, keyName);
return contextRoot + keyName;
}
public String storeContactProfilePicture(Long idUser, Long idContact, InputStream inStream) {
String keyName = getContactProfilePictureKey().replaceAll("<<idUsr>>", idUser.toString()).replaceAll("<<idContact>>", idContact.toString());
storeObject(inStream, keyName);
return contextRoot + keyName;
}
public String storeUserProfilePicture(Long idUser, String fileName, String accountType) {
String keyName = getUserPictureKey().replaceAll("<<idUsr>>", idUser.toString()).replace("<<socialNetwork>>", accountType);
storeObjectFromFileName(fileName, keyName);
return contextRoot + keyName;
}
private void storeObjectFromFileName(String fileName, String keyName) {
try {
logger.info("Uploading " + fileName + " to " + keyName);
InputStream inStream = new URL(fileName).openStream();
storeObject(inStream, keyName);
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
}
private void storeObject(InputStream inStream, String keyName) {
try {
this.s3client.putObject(new PutObjectRequest(getBucketName(), keyName, inStream, null));
} catch (AmazonServiceException ase) {
logger.error("Caught an AmazonServiceException, which "
+ "means your request made it "
+ "to Amazon S3, but was rejected with an error response"
+ " for some reason.");
logger.error("Error Message: " + ase.getMessage());
logger.error("HTTP Status Code: " + ase.getStatusCode());
logger.error("AWS Error Code: " + ase.getErrorCode());
logger.error("Error Type: " + ase.getErrorType());
logger.error("Request ID: " + ase.getRequestId());
} catch (AmazonClientException ace) {
logger.error("Caught an AmazonClientException, which "
+ "means the client encountered "
+ "an internal error while trying to "
+ "communicate with S3, "
+ "such as not being able to access the network.");
logger.error("Error Message: " + ace.getMessage());
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
}
public String getContextRoot() {
return contextRoot;
}
public void setContextRoot(String contextRoot) {
this.contextRoot = contextRoot;
}
public String getBucketName() {
return bucketName;
}
public void setBucketName(String bucketName) {
this.bucketName = bucketName;
}
private String getContactProfilePictureKey() {
return contactProfilePictureKey;
}
private void setContactProfilePictureKey(String contactProfilePictureKey) {
this.contactProfilePictureKey = contactProfilePictureKey;
}
private String getUserPictureKey() {
return userPictureKey;
}
private void setUserPictureKey(String userPictureKey) {
this.userPictureKey = userPictureKey;
}
}
The classes that use S3Transfer now have the following code:
#Autowired
private S3Transfer s3Transfer;
Both /WEB-INF/applicationContext.xml and /WEB-INF/app-web-servlet.xml have the following elements within the complex bean element:
<context:annotation-config />
<context:component-scan base-package="com.company.app" />
<context:property-placeholder location="/WEB-INF/servlet.properties" />
When I restart Tomcat, initialization fails. Here are some of the relevant log entries:
[localhost-startStop-1] 03 Dec 2014 18:39:03,407 INFO : org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean definitions from ServletContext resource [/WEB-INF/applicationContext.xml]
[localhost-startStop-1] 03 Dec 2014 18:39:03,926 INFO : org.springframework.context.annotation.ClassPathBeanDefinitionScanner - JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning
[localhost-startStop-1] 03 Dec 2014 18:39:05,990 INFO : org.springframework.context.annotation.ClassPathBeanDefinitionScanner - JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning
[localhost-startStop-1] 03 Dec 2014 18:39:07,983 INFO : org.springframework.context.support.PropertySourcesPlaceholderConfigurer - Loading properties file from ServletContext resource [/WEB-INF/servlet.properties]
[localhost-startStop-1] 03 Dec 2014 18:39:08,708 INFO : org.springframework.beans.factory.support.DefaultListableBeanFactory - Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory#63655d7a: defining beans [... {long list, but s3TransferImpl is not in the list} ...]; root of factory hierarchy
[localhost-startStop-1] 03 Dec 2014 18:39:10,667 INFO : org.springframework.jdbc.datasource.DriverManagerDataSource - Loaded JDBC driver: com.mysql.jdbc.Driver
[localhost-startStop-1] 03 Dec 2014 18:39:20,152 ERROR: org.springframework.web.context.ContextLoader - Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.filterChains': Cannot resolve reference to bean 'org.springframework.security.web.DefaultSecurityFilterChain#0' while setting bean property 'sourceList' with key [0]; nested exception is ... {long list of nested exceptions}...; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.company.app.utilities.S3Transfer] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:329)
Update 2014-12-03 14:50 EST:
Apparently, both my interface and class needed an #Service annotation, as Tomcat restarted successfully. What is the purpose of this annotation?
The package of the new class i.e. com.company.app.service needs to be added to the xml file which has the spring configuration.
You need to add this to your spring XML configuration file
<beans>
<context:component-scan base-package="com.package.containing.yourclass" />
</beans>
You need to this so that Spring understands which classes it needs to scan for annotations and/or creating beans.
Could you please share the code where you are trying to access the variable. If it is inside contructor, then you will get error. As singleton beans being instiated during loading will not be able to access these values from property configurator. You may consider to move your code to in-it method, so that your variable will set while accessing the field.
Also, confirm if your class is being instantited by spring container, not by some other means like new operator