Tuesday, 15 April 2014

java - Why is my Spring @Autowired field null? -



java - Why is my Spring @Autowired field null? -

note: intended canonical reply mutual problem.

i have spring @service class (mileagefeecalculator) has @autowired field (rateservice), field null when seek utilize it. logs show both mileagefeecalculator bean , mileagerateservice bean beingness created, nullpointerexception whenever seek phone call mileagecharge method on service bean. why isn't spring autowiring field?

controller class:

@controller public class mileagefeecontroller { @requestmapping("/mileage/{miles}") @responsebody public float mileagefee(@pathvariable int miles) { mileagefeecalculator calc = new mileagefeecalculator(); homecoming calc.mileagecharge(miles); } }

service class:

@service public class mileagefeecalculator { @autowired private mileagerateservice rateservice; // <--- should autowired, null public float mileagecharge(final int miles) { homecoming (miles * rateservice.ratepermile()); // <--- throws npe } }

service bean should autowired in mileagefeecalculator isn't:

@service public class mileagerateservice { public float ratepermile() { homecoming 0.565f; } }

when seek get /mileage/3, exception:

java.lang.nullpointerexception: null @ com.chrylis.example.spring_autowired_npe.mileagefeecalculator.mileagecharge(mileagefeecalculator.java:13) @ com.chrylis.example.spring_autowired_npe.mileagefeecontroller.mileagefee(mileagefeecontroller.java:14) ...

the field annotated @autowired null because spring doesn't know re-create of mileagefeecalculator created new , didn't know autowire it.

the spring inversion of command (ioc) container has 3 main logical components: registry (called applicationcontext) of components (beans) available used application, configurer scheme injects objects' dependencies them matching dependencies beans in context, , dependency solver can @ configuration of many different beans , determine how instantiate , configure them in necessary order.

the ioc container isn't magic, , has no way of knowing java objects unless somehow inform of them. when phone call new, jvm instantiates re-create of new object , hands straight you--it never goes through configuration process. there 3 ways can beans configured.

i have posted of code, using spring boot launch, @ this github project; can @ total running project each approach see need create work. tag nullpointerexception: nonworking

inject beans

the preferable alternative allow spring autowire of beans; requires to the lowest degree amount of code , maintainable. create autowiring work wanted, autowire mileagefeecalculator this:

@controller public class mileagefeecontroller { @autowired private mileagefeecalculator calc; @requestmapping("/mileage/{miles}") @responsebody public float mileagefee(@pathvariable int miles) { homecoming calc.mileagecharge(miles); } }

if need create new instance of service object different requests, can still utilize injection using the spring bean scopes.

tag works injecting @mileagefeecalculator service object: working-inject-bean

use @configurable

if need objects created new autowired, can use spring @configurable annotation along aspectj compile-time weaving inject objects. approach inserts code object's constructor alerts spring it's beingness created spring can configure new instance. requires bit of configuration in build (such compiling ajc) , turning on spring's runtime configuration handlers (@enablespringconfigured javaconfig syntax). approach used roo active record scheme allow new instances of entities necessary persistence info injected.

@service @configurable public class mileagefeecalculator { @autowired private mileagerateservice rateservice; public float mileagecharge(final int miles) { homecoming (miles * rateservice.ratepermile()); } }

tag works using @configurable on service object: working-configurable

manual bean lookup: not recommended

this approach suitable interfacing legacy code in special situations. preferable create singleton adapter class spring can autowire , legacy code can call, possible straight inquire spring application context bean.

to this, need class spring can give reference applicationcontext object:

@component public class applicationcontextholder implements applicationcontextaware { private static applicationcontext context; @override public void setapplicationcontext(applicationcontext applicationcontext) throws beansexception { context = applicationcontext; } public static applicationcontext getcontext() { homecoming context; } }

then legacy code can phone call getcontext() , retrieve beans needs:

@controller public class mileagefeecontroller { @requestmapping("/mileage/{miles}") @responsebody public float mileagefee(@pathvariable int miles) { mileagefeecalculator calc = applicationcontextholder.getcontext().getbean(mileagefeecalculator.class); homecoming calc.mileagecharge(miles); } }

tag works manually looking service object in spring context: working-manual-lookup

java spring null nullpointerexception autowired

No comments:

Post a Comment