Properties file injection not working in spring - java

I am trying to use the properties file and inject it to my fields of a class, but I am getting null .
I have created a properties file called fortune.properties:
fortune1=Have a good day
fortune2=Have a bad day
fortune3=Have a medioccure day
Then I am loading it in the applicationContext.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- Enable Component Scanning -->
<context:component-scan base-package="com.luv2code.springdemo"></context:component-scan>
<context:property-placeholder location="classpath:fortune.properties" />
</beans>
In the RandomFortuneClass, I am using value injection using #Value() annotation:
package com.luv2code.springdemo;
import java.util.Random;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
#Component()
public class RandomFortuneService implements FortuneService {
#Value("${fortune1}")
private String fortune1;
#Value("${fortune2}")
private String fortune2;
#Value("${fortune3}")
private String fortune3;
String[] fortunes = new String[] {fortune1, fortune2, fortune3};
private Random random = new Random();
#Override
public String getFortune() {
int index = random.nextInt(fortunes.length);
return fortunes[index];
}
}
Then I am declaring fortuneService in SwimCoach class using constructor injection:
package com.luv2code.springdemo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
#Component()
public class SwimCoach implements Coach {
private FortuneService fortuneService;
#Autowired
SwimCoach(#Qualifier("randomFortuneService") FortuneService fs) {
fortuneService = fs;
}
#Override
public String getDailyWorkout() {
System.out.println();
return "Swim 5m everyday";
}
#Override
public String getDailyFortune() {
return fortuneService.getFortune();
}
}
Now when I try to call the method getDailyFortune in the AnnotationDemoApp class, I always get null as output.
package com.luv2code.springdemo;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AnnotationDemoApp {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Coach theCoach = context.getBean("swimCoach", Coach.class);
System.out.println(theCoach.getDailyFortune());
context.close();
}
}
What is the error here?
Kindly comment if more information is needed.
Here is my file hierarchy:
PS: I am following the spring & hibernate course for beginners by Chad Darby.

You simply need to move fortune.properties into /src/main/resources, but let me suggest a cleaner way...
First, drop the xml configuration, it's outdated by several years and everything you can do there can be done via java annotations.
Second, add your property files to src/main/resources.
Third, tell Spring where to resolve your properties from, you can do this by adding #PropertySources({#PropertySource("fortune.properties")}) to a configuration class like this (also note that I've added the #ComponentScan and #Configuration annotations here):
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.PropertySource;
#Configuration
#ComponentScan
#PropertySource("fortune.properties")
public class Config {
}
Fourth, in your main method, use the AnnotationConfigApplicationContext as opposed to the ClassPathXmlApplicationContext. I think you'll find it's much cleaner.
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
Coach theCoach = context.getBean("swimCoach", Coach.class);
System.out.println(theCoach.getDailyFortune());
}

Related

Spring MVC - Load bean definitions from appContext.xml programatically

I've been pulling my hair for hours on this one.
I am setting up a new Spring MVC REST servlet and I've been trying to avoid XML definitions this time and do it programatically.
To the problem: I am looking for a way to load bean definitions from applicationContext.xml while still having #ComponentScan(...) enabled (#Autowire/context.getBean(...) works in the latter).
I looked through the google trying countless combinations (I think, but I may have missed something) and found something that could help:
https://www.mkyong.com/spring/spring-mixing-xml-and-javaconfig/
... only it doesn't (#ImportResource("classpath*:applicationContext")).
Please bear in mind that following declarations to #ImportResource fail the deployment of artifact (built with Gradle) with no log whatsoever:
"applicationContext"
"classpath:applicationContext"
The application context is located just next to 'java' folder (Gradle folder structure [src/main/java]):
My root config:
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.context.annotation.ImportResource;
import org.springframework.stereotype.Controller;
#Configuration
#ImportResource("classpath:applicationContext.xml")
#ComponentScan(
basePackages = { "com.storfoome.backend" },
excludeFilters = {#Filter(classes = { Controller.class }, type = FilterType.ANNOTATION)}
)
public class ServiceRootConfig {
}
My web config:
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
#EnableWebMvc
#Configuration
#ComponentScan(
basePackages = { "com.storfoome.backend" },
useDefaultFilters = false,
includeFilters = { #Filter(classes = { Controller.class }, type = FilterType.ANNOTATION) }
)
public class ServiceWebConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("*/resources/**").addResourceLocations("/resources/");
}
}
My servlet initializer:
import com.storfoome.backend.framework.rest.config.ServiceRootConfig;
import com.storfoome.backend.framework.rest.config.ServiceWebConfig;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public class SofomeServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
private static final String DEFAULT_SERVLET_MAPPING = "/sofome/*";
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[] { ServiceRootConfig.class };
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[] {ServiceWebConfig.class};
}
#Override
protected String[] getServletMappings() {
return new String[] { DEFAULT_SERVLET_MAPPING };
}
}
The bean with #Autowire from XML declared bean:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
#Component("autowireTest")
public class AutowireTest {
#Autowired
private SofomePropertyResource propertyResource;
public void printProperty() {
System.out.println(propertyResource.getProperty("helloWorld"));
}
public AutowireTest() {
}
private String test;
public String getTest() {
return test;
}
public void setTest(String test) {
this.test = test;
}
}
My applicationContext.xml:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="sofomeProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="locations">
<list>
<value>classpath*:sofome.properties</value>
</list>
</property>
</bean>
</beans>
So, while I was posting this I also resolved this. So for anyone whould would be struggling with this.
Everything related to Java code in the question is correct apparently.
The thing was, with Gradle and it's "war" plugin. So, it looks into 'resource' folder by default for everything not *.java [citation needed].
I moved the applicationContext.xml to 'resource/config', launched Gradle build process (NOTE: I do not have any custom script written for WAR generation. Just "apply plugin: 'war'"):

Spring loads two different instances when loaded with BeanFactory and ApplicationContext with a single spring.xml file

I was writing some code to study different ways for getting bean from spring container. I have kept the code very simple to address the issue I had .
I have written below classes
Triangle Class
package org.studyspring.beanfactory;
public class Triangle {
public String draw() {
return "Triangle Drawn";
}
}
Spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id ="triangle" class ="org.studyspring.beanfactory.Triangle"/>
</beans>
Test class
package org.studyspring.beanfactory;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.FileSystemResource;
import static org.junit.Assert.assertEquals;
public class BeanFactoryTest {
private static BeanFactory factory;
private static ApplicationContext context;
#BeforeClass
public static void setupBeforeClass(){
factory = new XmlBeanFactory(new FileSystemResource("./basicSpring/src/test/resources/spring.xml"));
context= new ClassPathXmlApplicationContext("spring.xml");
}
#Test
public void getTriangleBean_WithBeanFactory(){
Triangle triangle = (Triangle) factory.getBean("triangle");
String message = triangle.draw();
assertEquals("Triangle Drawn",message);
}
#Test
public void getTriangleBean_WithApplicationContext(){
Triangle triangle = (Triangle) context.getBean("triangle");
String message = triangle.draw();
assertEquals("Triangle Drawn",message);
}
#Test
public void triangleBean_ShouldBeSame_WithApplicationContextAndWithBeanFactory(){
Triangle triangle = (Triangle) factory.getBean("triangle");
Triangle triangle1 = (Triangle) context.getBean("triangle");
String message = triangle.draw();
assertEquals(triangle,triangle1);
}
}
I thought my testcase triangleBean_ShouldBeSame_WithApplicationContextAndWithBeanFactory should have been passed but actually it failed with below error
Expected :org.studyspring.beanfactory.Triangle#22c1609b
Actual :org.studyspring.beanfactory.Triangle#45ad71f0
I am asking this question because I had below assumptions
when spring container initializes a bean its default scope is Singleton
spring container should use only one instance of bean
moreover ApplicationContext extends BeanFactory (indirectly)
We could use BeanFactory and ApplicationContext alternatively
My question is about the fundamentals ,is it the correct behaviour by spring container to load two seperate instances each for beanFactory and ApplicationContext?
This is because you create 2 different containers. You can make 2 ApplicationContexts
ApplicationContext context1;
ApplicationContext context2;
still there will be two different instances of Triangle in them

No XML Spring ApplicationContext

I am trying create an project with and without spring xml configurations.
First at all, I create my xml configuration like that:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.1.xsd">
<bean id="memoryManagerProduct" class="br.com.caelum.stock.ProductManager">
<constructor-arg ref="memoryProductDAO"/>
</bean>
<bean id="memoryProductDAO" class="br.com.caelum.stock.dao.MemoryProductDAO"/>
</beans>
That I created my non XML configuration (I do not know if is right base in the fact that I do not know how invoke that)
package br.com.caelum.spring.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import br.com.caelum.stock.ProductManager;
import br.com.caelum.stock.dao.MemoryProductDAO;
import br.com.caelum.stock.dao.Persistable;
import br.com.caelum.stock.model.Product;
#Configuration
public class AppConfig {
#Bean
public Persistable<Product> memoryProductDAO(){
return new MemoryProductDAO();
}
#Bean
public ProductManager memoryProductManager(){
return new ProductManager(memoryProductDAO());
}
}
Than I created an JUnit test:
package br.com.caelum.stock;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import br.com.caelum.stock.model.Product;
public class ProductManagerTest {
private ProductManager manager;
#Test
public void testSpringXMLConfiguration() {
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring.xml");
manager = (ProductManager) context.getBean("memoryManagerProduct");
Product product = new Product();
product.setDescription("[Book] Spring in Action");
product.setQuantity(10);
manager.add(product);
assertThat(manager.getProducts().get(0).getDescription(), is("[Book] Spring in Action"));
}
#Test
public void testSpringWithoutXMLConfiguration() {
ApplicationContext context = ?
}
}
How can I inject the configurations that are in my AppConfig to do a similar test as in my testSpringXMLConfiguration?
There are good examples in the Spring reference guide here: http://docs.spring.io/spring/docs/current/spring-framework-reference/html/beans.html#beans-java-instantiating-container
In short, you would do this:
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
manager = (ProductManager) context.getBean("memoryManagerProduct");
However a better way of testing with Spring would be to use the spring-test support, details are here - http://docs.spring.io/spring/docs/current/spring-framework-reference/html/testing.html#integration-testing-annotations
You can do something like this with spring-test support:
#ContextConfiguration(classes = AppConfig.class)
#RunWith(SpringJUnit4ClassRunner.class)
public class ProductManagerTest {
#Autowired
private ProductManager manager;
#Test
public void testSpringXMLConfiguration() {
//use the productmanager in a test..
}
}

Spring - NullPointerException when autowiring [duplicate]

This question already has answers here:
Using Spring 3 autowire in a standalone Java application
(5 answers)
Closed 9 years ago.
Is there a way to run Spring application configured by annotation, directly from main method?
I'm still getting NullPointerException runing code below. Note that I'm not using SpringMVC and when I'm using beans defined inside context.xml, injected inside main method by context.getBean method, all code works perfect (without error) - but I just wondering if it is a way to manage runing this only with annotations?
//IElem.java
package com.pack.elem;
public interface IElem {
public abstract String sayHello();
}
//Elem.java
package com.pack.elem;
import org.springframework.stereotype.Component;
#Component
public class Elem implements IElem{
#Override
public String sayHello() {
return ("Hello from Elem class object");
}
}
//RunElem.java
package com.pack.elem;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
#Component
public class RunElem {
#Autowired
private IElem elem;
public void runHello(){
System.out.println(elem.sayHello());
}
}
//Main.java
package com.pack.main;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.pack.elem.RunElem;
public class Main {
#Autowired
private RunElem runelem;
public static void main(String[] args) {
ApplicationContext context= new ClassPathXmlApplicationContext("/META-INF/application-context.xml");
new Main().runRun();
}
private void runRun(){
runelem.runHello();
}
}
<!--/META-INF/application-context.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<context:annotation-config/>
<context:component-scan base-package="com.pack"/>
</beans>
Put simply, Spring is autowiring if it is the one instantiating the bean. So you have to use getBean(). If you want to use annotations only, something like this should work:
#Component
public class Main {
#Autowired
private RunElem runelem;
public static void main(String[] args) {
ApplicationContext context= new ClassPathXmlApplicationContext("/META-INF/application-context.xml");
Main mainBean = context.getBean(Main.class);
mainBean.runRun();
}
private void runRun(){
runelem.runHello();
}
}
Alternatively you can autowire an existing bean as shown below, but this is not a recommended Spring usage:
public class Main {
#Autowired
private RunElem runelem;
public static void main(String[] args) {
ApplicationContext context= new ClassPathXmlApplicationContext("/META-INF/application-context.xml");
Main mainBean = new Main();
context.getAutowireCapableBeanFactory().autowireBean(mainBean);
mainBean.runRun();
}
private void runRun(){
runelem.runHello();
}
}

Spring AOP #Pointcut not triggering

I want to trigger a method when a particular method from another class is invoked that is why I thought of using #Pointcut.
The code below is almost identical to the that I am coding and I don't what else I have to add.
public class OrgManagerImpl implements OrgManager {
public IOrg getOrg(String orgShortName) {
}
}
and this is the class that will should be triggered:
#Aspect
public class OrgManagerSynchronizer {
#Pointcut("execution(* com.alvin.OrgManager.getOrg(..))")
public void classMethods() {}
#Before("classMethods()")
public void synchronize(JoinPoint jp) {
//code should be executed. but does not execute.
}
}
and in my .xml this was specified:
aop:aspectj-autoproxy
What more should I add? What to do next?
Check below things.
1) Check if OrgManagerImpl is either defind as bean in context xml or it is marked as #Component & in context xml you have or that classes's package.
2) If above thing is correct then try changing pointcut as below
#Pointcut("execution(* get*(..))")
This pointcut intercepts all get methods. See if with this point cut your synchronize method is working or not. If it works then at least your spring configurations are fine. you just need to refine pointcut expression. But if this also doesn't work then there is something wrong with your spring aop configuration itself, so we can concentrate on those.
Also if this doesn't work then try to give some more info like you context xml, bean java classes etc.
Two things you need to check.
aop:aspectj-autoproxy is enabled in configuration
The Point Cut / Aspect / Target are spring bean
The below is my xml config example.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<aop:aspectj-autoproxy/>
<context:component-scan base-package="com.techoffice"/>
<bean class="com.techoffice.example.ExampleAspect"/>
</beans>
ExampleAspect.java
package com.techoffice.example;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
#Aspect
public class ExampleAspect {
#Pointcut("execution (* com.techoffice..*(..))")
public void anyRun() {}
#Before(value="anyRun()")
public void beforeAnyRun(JoinPoint jointPoint){
System.out.println("Before " + jointPoint.getClass().getName() + "." + jointPoint.getSignature().getName());
}
#After(value="anyRun()")
public void afterAnyRun(JoinPoint jointPoint){
System.out.println("After " + jointPoint.getClass().getName() + "." + jointPoint.getSignature().getName());
}
}
HelloWorldExample
package com.techoffice.example;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Component;
#Component
public class HelloWorldExample {
public void run(){
System.out.println("run");
}
public static void main(String[] args){
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
HelloWorldExample helloWorldExample = context.getBean(HelloWorldExample.class);
helloWorldExample.run();
}
}

Categories