bean scope in xml not working - spring

singleton bean scope in XML spring not working.only prototype working.Even without any scope tag prototype is working.
XML snippet:
<?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-3.0.xsd">
<bean id="restaurant" class="bean_scope.Restaurant1" scope="singleton"> <!-- scope="singleton" -->
</bean>
</beans>
Java class for setter methods:
package bean_scope;
public class Restaurant1 {
private String welcomeNote;
public void setWelcomeNote(String welcomeNote) {
this.welcomeNote = welcomeNote;
}
public void greetCustomer(){
System.out.println(welcomeNote);
}
}
Java Spring Test class:
package bean_scope;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Restaurant1Test {
public static void main(String[] args) {
Restaurant1 restaurantOb1=(Restaurant1) new ClassPathXmlApplicationContext("bean_scope/SpringConfig1.xml")
.getBean("restaurant");
restaurantOb1.setWelcomeNote("Welcome");
restaurantOb1.greetCustomer();
Restaurant1 restaurantOb2=(Restaurant1) new ClassPathXmlApplicationContext("bean_scope/SpringConfig1.xml")
.getBean("restaurant");
//restaurantOb2.setWelcomeNote("Hello");
restaurantOb2.greetCustomer();
}
}
Output:
Welcome
null
Please help me with this why singleton scope is not working

Since you create two independent instances of ClassPathXmlApplicationContext, each one will have its own singleton instance of the bean. The singleton scope means there will only be one instance of the bean within the Spring context - but you have two contexts there.
This would produce the result you're expecting:
ApplicationContext ctx = new ClassPathXmlApplicationContext("bean_scope/SpringConfig1.xml");
Restaurant1 restaurantOb1=(Restaurant1) ctx.getBean("restaurant");
restaurantOb1.setWelcomeNote("Welcome");
restaurantOb1.greetCustomer();
Restaurant1 restaurantOb2=(Restaurant1) ctx.getBean("restaurant");
//restaurantOb2.setWelcomeNote("Hello");
restaurantOb2.greetCustomer();

Related

How to pass base package as a variable inside pointcut expression in Spring AOP?

I am creating a java library for logging purpose so that if any application uses my library then spring AOP's advices are applied to each method of the application. But in my library, I don't know the base package of the applications that will be using it. So, the applications should specify their base package in the application.properties file and my library will use it and put it in my pointcut as a variable. But seems like pointcut expressions only accepts contants inside it.
I don't want to go for annotation based approach.
#Component
#Aspect
#Slf4j
public class LoggingAop {
#Value("${base.package}")
String basePackage;
#Pointcut("within("+basePackage+"..*)") //error
public void logAllMethods()
{
}
}
Answers for the following questions explains why this is not possible with annotation based Spring AOP configuration
Get rid of "The value for annotation attribute must be a constant expression" message
How to supply value to an annotation from a Constant java
Spring boot supports xml based configurations and the requirement can be achieved as follows.
Assuming we have to intercept all the method calls within base package com.app.service
Have an entry in resources/application.properties.
base.package=com.app.service
An Aspect to log method calls within the base package can be as follows
package com.app.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LogAspect {
Logger log = LoggerFactory.getLogger(LogAspect.class);
public Object logAllMethods(ProceedingJoinPoint pjp) throws Throwable {
log.info("Log before method call");
try {
return pjp.proceed();
}finally {
log.info("Log after method call");
}
}
}
The aop configuration can be defined as follows .
File : resources/aop-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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="logAspect" class="com.app.aspect.LogAspect"></bean>
<aop:config>
<aop:aspect id="logallaspect" ref="logAspect" >
<!-- #Around -->
<aop:pointcut id="logAllMethodsAround" expression="within(${base.package}..*)" />
<aop:around method="logAllMethods" pointcut-ref="logAllMethodsAround" />
</aop:aspect>
</aop:config>
</beans>
Do note that the pointcut expression is constructed with the application.properties entry.
Remember to load the aop-application-context.xml as follows
#SpringBootApplication
#ImportResource("classpath:aop-application-context.xml")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
The above code will advice all the interceptable Spring bean method calls within the defined base package and logs them .
Hope this helps.

Spring Autowiring a list into a bean results in a NoSuchBeanDefinitionException

In a Spring 3.1.3.RELEASE project I want to create and autowire a list that contains some enum to some service.
Unfortunately the autowiring fails (NoSuchBeanDefinitionException), while I can retrieve the bean in the context and manually wire the dependency.
Here is a small testcase showcasing the issue (using Spring 3.1.3 and JUnit):
The XML context (int package /junk):
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
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/util http://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="junk"/>
<util:list id="myList" value-type="junk.GreatThings">
<value>SUPER</value>
<value>COOL</value>
</util:list>
</beans>
The enum:
package junk;
public enum GreatThings {AMAZING, GREAT, SUPER, COOL}
The test class (in package junk - I've removed the import for clarity):
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = {"classpath*:junkcontext.xml"})
public class TestAutowiringSupport {
#Autowired #Qualifier("myList") List<GreatThings> greatThings;
#Test public void testSuperCool() {
Assert.assertThat(greatThings, hasItem(SUPER));
Assert.assertThat(greatThings, hasItem(COOL));
}
}
This result in a NoSuchBeanDefinitionException.
I have try to put a #Qualifier with my bean id to help Spring to perform the wiring without any success.
My IDE is however able to detect the wiring by itself:
And if I use the Spring lifecycle callbacks to get back the bean and wire it manually then, it is fine.
Version that compiles and runs fine:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = {"classpath*:junkcontext.xml"})
public class TestAutowiringSupport implements ApplicationContextAware
{
ApplicationContext ctx;
List<GreatThings> greatThings;
#Override
public void setApplicationContext(ApplicationContext ctx) throws BeansException {this.ctx = ctx;}
#PostConstruct
public void manualWiring() {greatThings = (List<GreatThings>) ctx.getBean("myList");}
#Test public void testSuperCool() {
Assert.assertThat(greatThings, hasItem(SUPER));
Assert.assertThat(greatThings, hasItem(COOL));
}
}
What's wrong with the autowiring in this case ?
Looks like some problem with generics.
With Spring 4.1 I am able to execute this code: where greatThings is of type List<Object>
#Qualifier("myList")
#Autowired List<Object> greatThings;
#Test
public void testSuperCool() {
Assert.assertThat(greatThings, Matchers.hasSize(2));
Assert.assertThat(greatThings, Matchers.hasItem(GreatThings.SUPER));
Assert.assertThat(greatThings, Matchers.hasItem(GreatThings.COOL));
}
As stated in the reference documentation, placing the #Autowired annotation over a typed collection means "find all beans of the given type (GreatThings in your case), put them in a collection and inject that collection". You are getting the exception because there are no beans of type GreatThings declared.
The problem is that there is no easy way to declare enum values as beans. Then again I don't see the use case to be honest.

How to load Spring applicationContext into Jersey Application

I'm creating a Jersey JAX-RS web service with the following:
package com.mycompany.rest.config;
import java.util.Set;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
#ApplicationPath("")
public class ApplicationConfig extends Application {
#Override
public Set<Class<?>> getClasses() {
return getRestResourceClasses();
}
private Set<Class<?>> getRestResourceClasses() {
Set<Class<?>> resources = new java.util.HashSet<Class<?>>();
resources.add(com.mycompany.rest.controllers.UserController.class);
return resources;
}
}
However, when I try and integrate a spring applicationContext such as the following :
<?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">
<context:component-scan base-package="com.mycompany.rest.user"/>
<bean id="userService" class="com.mycompany.rest.user.UserServiceImpl" />
</beans>
I get null pointers from my controller class for the userService being loaded by the bean pasted above. I'm assuming this is because the application context is not being loaded into the Jersey application.
Is there a way of doing this?
If you want to inject Spring beans into your Jersey resource classes, you need to add jersey-spring3 dependency to your class path. see https://jersey.java.net/documentation/latest/spring.html
An hello-world example can be found at https://github.com/jersey/jersey/tree/2.19/examples/helloworld-spring-webapp
I had the same problem, and i fixed it by adding #autowired to my service, and extending SpringBeanAutowiringSupport like the following :
#Path("/mails")
public class MailController extends SpringBeanAutowiringSupport{
#Autowired
private MailService mailService;
#GET
#Path("/{code}")
#Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public String getMails(#PathParam("code") String code) throws Exception {
//function logic
}
Note that this is working without integrating jersey-springx.jar
And I'm using Spring 3 along with jersey-bundle-1.19.1.jar

Dependency Injection in Spring?

How can we know if spring framework is using constructor based dependency injection or setter method based dependency injection, when both the constructor and setter method is defined?
for example.. I have two java classes as follows..
TextEditor.java
public class TextEditor {
private SpellChecker spellChecker;
TextEditor(SpellChecker spellChecker){
this.spellChecker = spellChecker;
}
public void setSpellChecker(SpellChecker spellChecker) {
this.spellChecker = spellChecker;
}
// a getter method to return spellChecker
public SpellChecker getSpellChecker() {
return spellChecker;
}
public void spellCheck() {
spellChecker.checkSpelling();
}
}
and
SpellChecker.java
public class SpellChecker {
public SpellChecker(){
System.out.println("Inside SpellChecker constructor." );
}
public void checkSpelling(){
System.out.println("Inside checkSpelling." );
}
}
in configuration file, pom.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-3.0.xsd">
<!-- Definition for textEditor bean using inner bean -->
<bean id="textEditor" class="com.tutorialspoint.TextEditor">
<property name="spellChecker">
<bean id="spellChecker" class="SpellChecker"/>
</property>
</bean>
</beans>
now, how can we know that spring has added dependency using Constructor or using Setter method?
When using a <property>, spring injects dependencies via setter.
If you want to inject it via constructor, you use <constructor-arg>.
Also see: http://docs.spring.io/spring/docs/current/spring-framework-reference/html/beans.html#beans-factory-collaborators
It is all about developer choice how does he/she configure spring to inject dependency.
Since everyone could write big wall of text about how Dependency Injection works you should see/read this:
http://www.journaldev.com/2410/spring-dependency-injection-example-with-annotations-and-xml-configuration

while using Spring ApplicationContext as in the example below, are annotations taken care of

public class SomeClass {
#Autowired
public WaterContainer wc;
private static int count = 0;
SomeClass(){ ++count;}
public static int testmethod() {
return count;
}
public static void main(String[] args) {
ApplicationContext context = new FileSystemXmlApplicationContext("spring-configuration\\beans.xml");
SomeClass obj = context.getBean(SomeClass.class);
//SomeClass obj2 = new SomeClass();
System.out.println("value of count "+SomeClass.testmethod());
if(obj.wc != null)
System.out.println("wc volume "+obj.wc.getCurrentVolume());
else
System.out.println("wc bean "+context.getBean(WaterContainer.class).getCurrentVolume()); //+(obj.wc==null)
}
}
The beans.xml file contains this :
<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 class="com.app.data.SomeClass"/>
<bean class="com.app.mechanism.WaterContainer">
<constructor-arg value="30"/>
</bean>
</beans>
the output that I got was as below but I expected the field wc in the SomeClass object to not be null, does that mean autowired annotations are not taken care of? or have I gone wrong somewhere?
value of count 1
wc bean 30
If so then how does
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = {"file:spring-configuration\\beans.xml"})
work for unit testing? how is the autowiring taken care of here
As M. Deinum stated, annotation configuration is built into some ApplicationContext implementations and not in others.
FileSystemXmlConfiguration is an implementation that does not have annotation configuration built into it. You can enable that annotation configuration with
<context:annotation-config />
(and the relevant namespace declarations).
Since that configuration was not enabled, #Autowired fields were not processed, and your SomeClass#wc field was left null.
The test configuration you've shown internally uses an AnnotationConfigApplicationContext where annotation configuration is built in.

Resources