Spring lookup-method and abstract class - java

Would like to understand how Spring creates a bean from an abstract class, as if it is instantiating an Abstract class, as it is known that is not possible. Would like to know, what is getting instantiated for the "abstractLookupBean" bean.
Thank you.
public abstract class AbstractLookupDemoBean implements DemoBean {
public abstract MyHelper getMyHelper();
public void someOperation() {
getMyHelper().doSomethingHelpful();
}
}
DemoBean class
public interface DemoBean {
public MyHelper getMyHelper();
public void someOperation();
}
applicationContext.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.1.xsd">
<bean id="helper" class="com.rami.methodlookup.helper.MyHelper" scope="prototype"/>
<bean id="abstractLookupBean" class="com.rami.methodlookup.helper.AbstractLookupDemoBean">
<lookup-method name="getMyHelper" bean="helper"/>
</bean>
<bean id="standardLookupBean" class="com.rami.methodlookup.helper.StandardLookupDemoBean">
<property name="myHelper">
<ref local="helper"/>
</property>
</bean>
</beans>
main class
public static void main(String[] args) {
GenericXmlApplicationContext ctx = null;
try{
ctx = new GenericXmlApplicationContext();
ctx.load("applicationContext.xml");
ctx.refresh();
DemoBean abstractBean = (DemoBean) ctx.getBean("abstractLookupBean"); //What is getting instantiated?
}finally{
ctx.close();
}

Please see spring documentation here
...If the method is abstract, the dynamically-generated subclass will implement the method. Otherwise, the dynamically-generated subclass will override the concrete method defined in the original class...

Related

Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'car' is defined

Can anyone tell me what is the error in this program and how to correct the error? I have given proper annotation and still getting errors.
I need help fixing this error I get when trying to deploy . Why isn't the Car bean being defined? Am I missing something in my web.xml or do I have to map the customerService somehow? I am using annotations for mapping. any help would be much appreciated. Here is the error log entry from the localhost log:
App.java
package om.venkatesh.omshakthi;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App
{
public static void main( String[] args )
{
ApplicationContext context=new ClassPathXmlApplicationContext("Spring.xml");
Car obj=(Car)context.getBean("car");
obj.drive();
}
}
Car.java
package om.venkatesh.omshakthi;
import org.springframework.stereotype.Component;
#Component
public class Car implements Vehicle{
public void drive()
{
System.out.println("Car");
}
}
Vehicle.java
package om.venkatesh.omshakthi;
public interface Vehicle {
void drive();
}
Spring.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-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<bean id="tyre" class="om.venkatesh.omshakthi.Tyre">
</bean>
</beans>
Without xml you can do it like this:
Create config class:
#Configuration
public class AppConfig {
#Bean
public Car car() {
return new Car();
}
}
Main class:
public class App {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(AppConfig.class);
ctx.refresh();
Car car = (Car) ctx.getBean("car");
car.drive();
}
}
Spring.xml has no bean with id "car" (although there is one for "tyre")
You need to define your bean in XML
<bean id="car" class="om.venkatesh.omshakthi.Car">
You don`t need #Component annotation when you use ClassPathXmlApplicationContext.
Just define a Car bean in your xml:
<bean id="car" class="om.venkatesh.omshakthi.Car">

NPE while accessing through #Autowired [duplicate]

This question already has answers here:
Why is my Spring #Autowired field null?
(21 answers)
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 2 years ago.
I have the below code in my SpringBoot project which is throwing NPE at a specific line mentioned.
Exception in thread "main" java.lang.NullPointerException
at com.temp.controller.Controller.triggerJob(Controller.java:15)
at com.temp.Application.main(Application.java:19)
Application.java
#Configuration
#SpringBootApplication
#ImportResource({"classpath:applicationContext.xml"})
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
Controller controller = new Controller();
controller.triggerJob();
}
}
Controller.java
#Controller
public class Controller {
#Autowired
private Service Service;
public void triggerJob() {
Service.selectRecords();
}
}
Service.selectRecords(); is where the NPE is being thrown
Service.java
public interface Service {
List<VO> selectRecords();
}
ServiceImpl.java
#Service
public class ServiceImpl implements Service {
#Autowired
private Dao dao;
#Override
public List<VO> selectRecords() {
return dao.selectRecords();
}
}
applicationContext.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:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util" xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/jdbc
http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<util:properties id="configProperties"
location="file:${app.config.home}/config/config-${spring.profiles.active}.properties" />
<context:property-placeholder
location="file:${app.config.home}/config/config-${spring.profiles.active}.properties" />
<bean id="crypt" class="com.temp.util.MyUtil">
<property name="userId" value="${username}"></property>
<property name="password" value="${password}"></property>
<property name="key" value="123456789012345678901234"></property>
</bean>
<bean id="datasource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${driver}" />
<property name="url" value="${connection}" />
<property name="username" value="#{crypt.userId}" />
<property name="password" value="#{crypt.password}" />
</bean>
<bean id="namedJdbcTemplate"
class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
<constructor-arg ref="datasource" />
</bean>
</beans>
I have a similar project like this and have compared the configuration of both and they are the same except for 2 things.
The spring boot starter version is 2.4.2 for this project and 1.5.3 for the other project.
Java version is 11 for this project and 1.8 for the other project.
Not sure where I'm going wrong.
Am I missing something? Kindly help.
You are creating new instance
Controller controller = new Controller();
manually and this instance is not in Spring context. Therefore, the injected (autowired) instance of Service is null. #Autowired only works when the instance exists in Spring context.
The best approach is to keep Controller testable is injection via constructor:
#Configuration
#SpringBootApplication
#ImportResource({"classpath:applicationContext.xml"})
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
Controller controller = new Controller(new ServiceImpl(new DaoImpl()));
controller.triggerJob();
}
}
Inject the instance via constructor:
#Controller
public class Controller {
private final Service Service;
public Controller(final Service Service) {
this.service = service;
}
public void triggerJob() {
Service.selectRecords();
}
}
And also inject the Dao dependency via constructor:
#Service
public class ServiceImpl implements Service {
private final Dao dao;
public ServiceImpl(final Dao dao) {
this.dao = dao;
}
#Override
public List<VO> selectRecords() {
return dao.selectRecords();
}
}
For Spring version above 4.3, #Autowired could be omitted from top of the constructor, Spring scans the injection automatically and injects the dependency via constructor.
For Spring version below 4.3, add #Autowired on top of constructors i.e.:
#Controller
public class Controller {
private final Service Service;
#Autowired
public Controller(final Service Service) {
this.service = service;
}
public void triggerJob() {
Service.selectRecords();
}
}

Field in Aspect injected after its first use, causing NullPointerException at startup

ABSTRACT:
I have some initialisation operations executed in #PostConstruct of #Service ServiceInitialiserFacsimile. Those operations include a call to a method after whose execution an Aspect (DoAttionalStuffAspect) is applied.
The Aspect is instantied through aspectOf, so it is handled by the Spring Container, but unfortunately its dependencies are injected AFTER the execution of ServiceInitialiserFacsimile #PostConstruct, resulting in a NullPointerException.
How can I tell the Spring Container to inject first the fields in the Aspect and then instantiate the ServiceInitialiserFacsimile ?
I tried with an Autowired constructor for the aspect, but I think in the end AspectJ requires the no-arg constructor, so it was no help
CODE
This is a Sample I created in order to reproduce the issue I have in a much more complicated app. Here is the project if you want to check it out. https://github.com/alessiop86/spring3-mvc-maven-xml-hello-world
Code below:
This is the initialisation class:
#Component
public class ServiceInitialiserFacsimile {
private final SampleService sampleService;
#Autowired
public ServiceInitialiserFacsimile(SampleService ss) {
this.sampleService = ss;
}
#PostConstruct
public void initialiseAllTheServices() {
this.sampleService.init();
}
}
This is the service with some custom logic that requires to be initialised by the ServiceInitialiserFacsimile #PostConstruct:
#Service
public class SampleService {
public void init() {
System.out.println("do some stuff");
try {
execute();
}
catch(Exception e) {
System.err.println("I do not want to block to whole framework initialisation");
}
}
#DoAdditionalStuff
public void execute() {
System.out.println("Phase 1");
}
}
This is the annotation I use in the aspect definition
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface DoAdditionalStuff {
}
This is the aspect
#Aspect
public class AdditionalStuffAspect {
private AdditionalStuffService service;
public AdditionalStuffService getService() {
return service;
}
public void setService(AdditionalStuffService service) {
this.service = service;
}
#Pointcut(value="execution(public * *(..))")
private void anyPublicMethod() { }
#AfterReturning("anyPublicMethod() && #annotation(doAdditionalStuff)")
public void afterReturning(JoinPoint jointPoint, DoAdditionalStuff doAdditionalStuff) {
System.out.println(jointPoint);
service.doStuff();
}
}
This is the service that is created, but not yet instantiated when the aspect is run:
#Service
public class AdditionalStuffService {
public void doStuff() {
System.out.println("Phase2: additional stuff");
}
}
Spring context xml configuration file:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<context:component-scan base-package="initialisation.mess"/>
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/views/jsp/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<mvc:resources mapping="/resources/**" location="/resources/"/>
<mvc:annotation-driven/>
<bean class="initialisation.mess.aspects.AdditionalStuffAspect" factory-method="aspectOf">
<property name="service" ref="additionalStuffService" />
</bean>
</beans>
I was able to enforce a dependency on the ServiceInitialiserFacsimile from the Aspect by setting an id in the xml:
<bean id="myAspect" class="initialisation.mess.aspects.AdditionalStuffAspect" factory-method="aspectOf">
<property name="service" ref="additionalStuffService" />
</bean>
and then specifying the dependency of ServiceInitialiserFacsimile from the spring managed AdditionalStuffAspect with a #DependsOn annotation:
#Component
#DependsOn("myAspect")
public class ServiceInitialiserFacsimile {
private final SampleService sampleService;
#Autowired
public ServiceInitialiserFacsimile(SampleService ss) {
this.sampleService = ss;
}
#PostConstruct
public void initialiseAllTheServices() {
this.sampleService.init();
}
}

extend abstract class and get its getter values using spring wiring

consider the following code:
public abstract class MachineInPitImpl extends AbstractPersistentObject implements MachineInPit {
protected PersonReference currentOperatorRef;
public void setCurrentOperatorRef(PersonReference currentOperatorRef) {
this.currentOperatorRef = currentOperatorRef;
this.currentOperatorObj = null;
}
public PersonReference getCurrentOperatorRef() {
return currentOperatorRef;
}
The above class is not wired with spring context, I need to extend this class and grab the values in the get method of this class in my new class.
I have wrote a class as this:
public class MachineOPJMXBeanImpl extends MachineInPitImpl {
public MachineOPJMXBeanImpl(){
}
#Override
public PersonReference getCurrentOperatorRef() {
return super.getCurrentOperatorRef();
}
}
But the value in this class get method is null.Why am I getting null value?
Here is the applicationcontext.xml file:
<bean id="machineOPJMXBean"
class="com.mincom.works.cc.personnel.node.MachineOPJMXBeanImpl" parent="machineInPitImpl">
<property name="currentOperatorRef" ref="currentOperatorRef"/>
</bean>
<bean id="machineInPitImpl" class="minestar.pitlink.domain.pitmodel.MachineInPitImpl" abstract="true" scope="singleton" lazy-init="true">
<property name="currentOperatorRef" ref="currentOperatorRef"/>
</bean>
<bean id="currentOperatorRef" class="minestar.machinetracking.domain.PersonReference"/>

How to make spring inject value into a static field

I know this may looks like a previously asked question but I'm facing a different problem here.
I have a utility class that has only static methods. I don't and I won't take an instance from it.
public class Utils{
private static Properties dataBaseAttr;
public static void methodA(){
}
public static void methodB(){
}
}
Now I need Spring to fill dataBaseAttr with database attributes Properties.Spring config is:
<?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:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd">
<util:properties id="dataBaseAttr"
location="file:#{classPathVariable.path}/dataBaseAttr.properties" />
</beans>
I already done it in other beans but the problem here in this class (Utils) isn't a bean, And if I make it a bean nothing changes I still can't use the variable since the class will not be instantiated and variable always equals null.
You have two possibilities:
non-static setter for static property/field;
using org.springframework.beans.factory.config.MethodInvokingFactoryBean to invoke a static setter.
In the first option you have a bean with a regular setter but instead setting an instance property you set the static property/field.
public void setTheProperty(Object value) {
foo.bar.Class.STATIC_VALUE = value;
}
but in order to do this you need to have an instance of a bean that will expose this setter (its more like an workaround).
In the second case it would be done as follows:
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="staticMethod" value="foo.bar.Class.setTheProperty"/>
<property name="arguments">
<list>
<ref bean="theProperty"/>
</list>
</property>
</bean>
On you case you will add a new setter on the Utils class:
public static setDataBaseAttr(Properties p)
and in your context you will configure it with the approach exemplified above, more or less like:
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="staticMethod" value="foo.bar.Utils.setDataBaseAttr"/>
<property name="arguments">
<list>
<ref bean="dataBaseAttr"/>
</list>
</property>
</bean>
I've had a similar requirement: I needed to inject a Spring-managed repository bean into my Person entity class ("entity" as in "something with an identity", for example an JPA entity). A Person instance has friends, and for this Person instance to return its friends, it shall delegate to its repository and query for friends there.
#Entity
public class Person {
private static PersonRepository personRepository;
#Id
#GeneratedValue
private long id;
public static void setPersonRepository(PersonRepository personRepository){
this.personRepository = personRepository;
}
public Set<Person> getFriends(){
return personRepository.getFriends(id);
}
...
}
.
#Repository
public class PersonRepository {
public Person get Person(long id) {
// do database-related stuff
}
public Set<Person> getFriends(long id) {
// do database-related stuff
}
...
}
So how did I inject that PersonRepository singleton into the static field of the Person class?
I created a #Configuration, which gets picked up at Spring ApplicationContext construction time. This #Configuration gets injected with all those beans that I need to inject as static fields into other classes. Then with a #PostConstruct annotation, I catch a hook to do all static field injection logic.
#Configuration
public class StaticFieldInjectionConfiguration {
#Inject
private PersonRepository personRepository;
#PostConstruct
private void init() {
Person.setPersonRepository(personRepository);
}
}
As these answers are old, I found this alternative. It is very clean and works with just java annotations:
To fix it, create a “none static setter” to assign the injected value for the static variable. For example :
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
#Component
public class GlobalValue {
public static String DATABASE;
#Value("${mongodb.db}")
public void setDatabase(String db) {
DATABASE = db;
}
}
https://www.mkyong.com/spring/spring-inject-a-value-into-static-variables/

Categories