Spring applicationContext not loading in a POJO - spring

My applicationContext is placed at path:src\main\webapp\WEB-INF\conf\applicationContext.xml
When I build this web application.I can see that conf folder is placed at {projectname.war}\WEB-INF\conf\applicationContext.xml.And Application works fine.
Now I happened to write a class with public static void main where I am trying to load applicationCOntext using below:
ApplicationContext context = new ClassPathXmlApplicationContext("../conf/applicationContext.xml");
ClassPathXmlApplicationContext("/WEB-INF/conf/applicationContext.xml");
ClassPathXmlApplicationContext("applicationContext.xml");
none of above seems to be working.
error is listed below:
Caused by: java.io.FileNotFoundException: class path resource [../conf/applicationContext.xml] cannot be opened because it does not exist.
Can someone point what wrong I am doing ?

Related

Data JPA Test with reactive spring

I want to test the repository layer and I'm using spring webflux. My test class is as follows
#RunWith(SpringRunner.class)
#DataJpaTest
public class DataTester {
#Autowired
private MyRepository repository;
#Test
.....
}
Even though this would work in spring-mvc when using spring-weblux I get the following error.
Failed to load ApplicationContext
java.lang.IllegalStateException: Failed to load ApplicationContext
...
Caused by: org.springframework.context.ApplicationContextException: Unable to start ReactiveWebApplicationContext due to missing ReactiveWebServerFactory bean.
How to resolve this? If I am to start the whole application context with #SpringBootApplication it works. Any other options without using that?
The reason for this was that in the application.properties the application type was set as reactive.
spring.main.web-application-type=reactive
This tries to auto configure a web server in this case a reactive web server. As #DataJpaTest does not provide a bean for that, this fails. This can be fixed in either two ways.
One is by Adding an application.properties file in the resources directory of the test package and setting the value as,sprig.main-web-application-type=none solves this issue.
Or we can simple pass a property value to the annotation as follows. #DataJpaTest(properties = "spring.main.web-application-type=none")
If you are using Spring Boot 2+ then only #DataJpaTest is enough on test class.
So your test class should be
#DataJpaTest
public class DataTester {
#Autowired
private MyRepository repository;
#Test
.....
}

Classloader-Leak with Spring and Log4j2

I am facing a classloader leak which I was able to repoduce it in a small project with only two classes and a few lines of code. It occurs as soon as a logger (Log4j2) is used.
Problem:
When deploying the application multiple times, the classes get loaded again and again until the PermGen space reaches its limit.
Steps to reproduce:
Download this small Maven-Project containing two classes. They are also depicted below.
Deploy application on a standard tomcat 7
Start jvisualvm and monitor the tomcat instance
Undeploy the application
Deploy the application again... even if you hit the 'perform gc' button, the classes will not be removed.
What I already tried without success:
Using the logger in a non-static field
Starting the VM with "-XX:+CMSClassUnloadingEnabled -XX:+UseConcMarkSweepGC"
Defining the logger in a Spring bean
Do you have any ideas, how to solve the problem?
Thanks in advance!
Here is the code contained in the project referenced above:
SpringContextInitializer.java (based on
http://docs.spring.io/spring/docs/3.2.x/javadoc-api/org/springframework/web/WebApplicationInitializer.html)
public class SpringContextInitializer implements WebApplicationInitializer {
#Override
public void onStartup(final ServletContext servletContext) throws ServletException {
servletContext.addListener(new Log4jServletContextListener());
servletContext.setAttribute("isLog4jAutoInitializationDisabled", false);
servletContext.setAttribute("log4jConfiguration", "classpath:log4j2.xml");
// Load a spring context and manage the lifecycle of the root
// application context
final AnnotationConfigWebApplicationContext appContext = new AnnotationConfigWebApplicationContext();
appContext.register(SpringConfiguration.class);
servletContext.addListener(new ContextLoaderListener(appContext));
// Enable the use of a session scope
servletContext.addListener(new RequestContextListener());
}
}
SpringConfiguration.java
#Configuration
public class SpringConfiguration {
private static final Logger LOGGER = LogManager.getLogger(SpringConfiguration.class.getName());
}
There are a number of known memory leak issues with log4j version 2.4 and 2.4.1. The upcoming version log4j-2.5 will address all of these.

#Profile cause Unable to start EmbeddedWebApplicationContext

im trying to use #Profile functionality to separate production/dev environment configuration and 'tests' config. But when I add #Profile to my configuration class I get:
Exception in thread "main" org.springframework.context.ApplicationContextException: Unable to start embedded container; nested exception is org.springframework.context.ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean.
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:124)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:476)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:109)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:691)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:320)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:952)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:941)
at mypackage.configuration.PhoenixConfiguration.main(PhoenixConfiguration.java:26)
Caused by: org.springframework.context.ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean.
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.getEmbeddedServletContainerFactory(EmbeddedWebApplicationContext.java:174)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.createEmbeddedServletContainer(EmbeddedWebApplicationContext.java:147)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:121)
... 7 more
Configuration class looks like this:
#Configuration
#EnableAutoConfiguration
#ComponentScan("mypackage")
#EnableJpaRepositories(basePackages = "mypackage.repository")
#EntityScan(basePackages = "mypackage.phoenix.domain")
#PropertySource("classpath:properties/application-production.properties")
#EnableWebMvc
#Profile("production")
public class PhoenixConfiguration extends WebMvcConfigurerAdapter{
public static void main(String[] args) throws Exception {
SpringApplication.run(PhoenixConfiguration.class, args);
}
}
ive tried to set active profile to production in application-production.properties
spring.profiles.active=production (with and without " )
or cmd command: mvn spring-boot:run -Dspring.profiles.active=production
nothing helps. Ofcourse everything works when I remove #Profile, but then I my tests are using production database ; )
If you add the profile your whole application basically stops working because your main entry point is annotated with #Profile.
I suggest you let Spring Boot do its work at the moment it appears as if you are trying to work very hard around Spring Boot and you are making things, imho, too complex.
Spring Boot will autodetect Spring Data JPA and the fact that you have Spring Web on your classpath. So remove #EnableJpaRepositories and #EnableWebMvc and don't let your class extends WebMvcConfigurerAdapter.
Spring boot by default will load the application.properties for you instead of putting in in properties either place it in the root of your classpath or config. At least remove the #PropertySource as Spring Boot will just load it. If you want to keep the properties path add the spring.config.location property which then points to your properties directory.
Finally I would probably also rename the file to PhoenixApplication but that is just me. That should leave you with something like
#Configuration
#EnableAutoConfiguration
#ComponentScan("mypackage")
#EntityScan(basePackages = "mypackage.phoenix.domain")
public class PhoenixApplication {
public static void main(String[] args) throws Exception {
SpringApplication.run(PhoenixApplication.class, args);
}
}
Now simply put your production configuration in the application.properties and put another one in src/test/resources to contain your test configuration. At runtime only the first will be available when testing the latter will override properties from the first.
If you really want to use profiles I would suggest doing it the other way around, configure for production and override for test. Then simply add #ActiveProfiles to your test case.
#ActiveProfiles("test")
#SpringApplicationConfiguration(classes=PhoenixApplication.class)
public class YourTest {}
This will start a test which will load the default application.properties and a application-test.properties which you can simply place in src/test/resources.

Can't get Spring bean

I have a Spring project in which I want to get a specific Spring bean defined in my Spring beans XML File. My Spring bean XML file is located at /WEB-INF/spring/root-context.xml.
Here is my code in the Service class:
ApplicationContext context = new ClassPathXmlApplicationContext("/WEB-INF/spring/root-context.xml");
Here is the error I get when I compile :
parsing XML document from class path resource [WEB-INF/spring/root-context.xml]; nested exception is java.io.FileNotFoundException: class path resource [WEB-INF/spring/root-context.xml] cannot be opened because it does not exist
Probably WEB-INF is not inside your classpath. I suggest to move the xml file in the classpath (for example src/main/resources/spring/root-context.xml). Then you can access it with: ApplicationContext context = new ClassPathXmlApplicationContext("/spring/root-context.xml"); If you're inside web application, Spring Mvc looks for th context in WEB-INF/<the name of the dispatcher servlet>-servlet.xml
If you want to access the context from WEB-INF you can load it using
GenericApplicationContext ctx = new GenericApplicationContext();
XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(ctx);
xmlReader.loadBeanDefinitions(new FileSystemResource(path));
A better way is using WebApplicationContextUtils or implement ApplicationContextAware. Not sure what your use case is...

Spring, using new ClassPathXmlApplicationContext and getting error being unable to find applicationContext.xml and others?

I am trying to follow this tutorial: http://www.vogella.de/articles/SpringDependencyInjection/article.html to use annotation dependency injection in my application. I set up the bean, etc like in the tutorial and then am trying to get an instance of the bean within my MainController class (a controller class that handles generating a specific page for my spring web mvc app).. I keep getting
SEVERE: Servlet.service() for servlet spring threw exception
java.io.FileNotFoundException: class path resource [WEB-INF/applicationContext.xml] cannot be opened because it does not exist
I am doing this in my MainController:
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
BeanFactory factory = context;
BeanIRPlus beanirPlus = (BeanIRPlus) factory
.getBean("BeanIRPlus");
IRPlusInterface irPlus = beanirPlus.getIRPlus();
I have searched and searched on this and yet to find an answer that fixes my problem. My applicationContext in in webapp/WEB-INF/ and my spring app seems to be working otherwise as it was handling requests, etc before this. I have tried putting the applicationContext.xml in WEB-INF classes but still nothing. Is there any workaround to make this not search the path this way as I think its doing a relative path search. Thanks for any advice
Not a direct answer, but here goes.
The tutorial you have referred is for dependency injection in a standalone application and not a web application. In case of web application, spring automatically loads the context files and initializes the beans. So you would not need any of the lines specified in the MainController.
Instead, you could do something like this to use beanIRPlus bean in your controller.
#Autowired
private BeanIRPlus beanIRPlus;

Resources