Problem with spring defined #ManagedProperty - spring

I'm currently mantainning a Maven based JSF Web Application combined with Spring Framework and JPA and connected to a SQL Server database.
Inside the application, I created one #ManagedBean class defined with the #ViewScoped and #Scope("view") annotations.
This class is named AvisoRecaladaBean and it has 3 attributes defined with the #ManagedProperty annotation as follows:
#ManagedProperty("#{jsf2Util}")
private Jsf2Util jsf2Util;
#ManagedProperty("#{avisoRecaladaService}")
private ISigcueCertAvisoRecaladaService avisoRecaladaService;
#ManagedProperty("#{usuarioService}")
private IUsuarioService usuarioService;
The first and third attributes were used in other managed beans in the same application. Also, IUsuarioService and ISigcueAvisoRecaladaService are interfaces, each one implemented by one class defined with the #Service annotation. The class that implements the latter interface also has the #Transactional annotation. JsfUtil is a class also defined with #Service.
Also, I defined one Integer attribute named folioBusqueda and one List<SigcueCertAvisoRecalada> attribute named listado. SigcueCertAvisoRecalada is an entity class pointing to a table in the database mencioned in the beginning.
Each attribute mentioned above has it's getter and setter.
In the other hand, I created one XHTML page named avisoRecalada.xhtml, that works with the AvisoRecaladaBean managed Bean.
The XHTML page has, among other things, one Panel Grid defined as follows:
<h:panelGrid columns="3">
<label>Ingrese NĂºmero de Folio: *</label>
<p:inputNumber placeholder="Folio del Aviso Recalada"
value="#{avisoRecaladaBean.folioBusqueda}"
required="true"
id="numeroFolio"/>
<p:commandButton value="Obtener Certificado Aviso"
actionListener="#{avisoRecaladaBean.buscarRegistro()}"
update="idTablaAviso"/>
<h:message for="numeroFolio" style="color:red"/>
</h:panelGrid>
The actionListener inside the command button refeers to the following method in AvisoRecaladaBean
public void buscarRegistro() {
SigcueCertAvisoRecalada item = avisoRecaladaService.findByFolio(folioBusqueda);
listado.clear();
if(item!=null) {
listado.add(item);
}
}
The Spring configuration is defined in an XML file defined as follows (I show only the important part):
<?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:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:drools="http://drools.org/schema/drools-spring"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://drools.org/schema/drools-spring http://anonsvn.jboss.org/repos/labs/labs/jbossrules/trunk/drools-container/drools-spring/src/main/resources/org/drools/container/spring/drools-spring-1.0.0.xsd
http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring/ehcache-spring-1.2.xsd
http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
">
<context:component-scan base-package="cl.sernapesca" />
<context:annotation-config />
<!-- Bean definitions -->
<tx:annotation-driven/>
<tx:jta-transaction-manager />
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="ignoreUnresolvablePlaceholders" value="true" />
<property name="locations">
<list>
<value>classpath:singleSingOn.properties</value>
<value>classpath:revision.properties</value>
<value>classpath:ldapExternos.properties</value>
</list>
</property>
</bean>
<!-- View Scope para JSF2 -->
<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
<property name="scopes">
<map>
<entry key="view">
<bean class="cl.sernapesca.mantenedorcentral.arquitectura.ViewScope" />
</entry>
</map>
</property>
</bean>
<!-- More Bean definitions -->
</beans>
The faces-config.xml has only the following managed-beans defined:
<managed-bean>
<managed-bean-name>currentDate</managed-bean-name>
<managed-bean-class>java.util.Date</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
And it's resolver is defined as:
<application>
<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
<!-- More configurations -->
</application>
When I deploy the application using a WildFly 10 Application Server, I get no error messages. Also, I get no errors when I access the XHTML page.
However, when I input one value in the input text and push the command button, I get one NullPointerException. The stack trace indicates that the exception were launched when trying to execute the first line of buscarRegistro().
After some debugging, I found that the avisoRecaladaService attribute was null, but the other two managed properties weren't.
I tried the following solutions with no avail
Add and/or replace #ManagedProperty with #Autowired
Use the #Qualifier annotation to name the bean (I named it "avisoRecaladaService") and use the current ApplicationContext to get the bean (Source: Spring Bean never set as ManagedProperty in JSF Bean). I got a NoSuchBeanException with this solution:
WebApplicationContext webAppContext = ContextLoader.getCurrentWebApplicationContext();
avisoRecaladaService = (IAvisoRecaladaService) webAppContext.getBean("avisoRecaladaService");
EDIT: Instantiate avisoRecaladaService directly. Not desirable. Also, autowired attributes of SigcueCertAvisoRecaladaService are null:
public void buscarRegistro() {
if(avisoRecaladaService==null)
avisoRecaladaService=new SigcueCertAvisoRecaladaService();
SigcueCertAvisoRecalada item = avisoRecaladaService.findByFolio(folioBusqueda);
listado.clear();
if(item!=null) {
if(listado==null)
listado=new ArrayList<>();
listado.add(item);
}
}
EDIT: Replace #ManagedAttribute with #Resource (Source: #ManagedProperty equivalent in Spring)
Replace #ManagedAttribute with #Inject (same source as the previous solution)
Any advice for a definitive solution would be really much obligated.
EDIT
As requested by Kukeltje, according to the application's pom.xml, the involved libraries are the following:
jboss-jsf-api 2.2
jboss-el-api 3.0 spec
spring-core 4.2.8
spring-web 4.2.8
spring-expression 4.2.8
spring-context-support 4.2.8
spring-web-mvc 4.2.8
JDK 1.8.0_191
Developed in Eclipse Oxygen (if relevant)

SOLVED
Thanks to a partner of mine, We discovered that #ManagedProperty is very sensitive about names. The name of the bean must be exactly the same as the class, with it's first letter in lower case. If the object is an interface instance, like in my case, it must be the name of the class implementing it.
So, I had to change this:
#ManagedProperty("#{avisoRecaladaService}")
private ISigcueCertAvisoRecaladaService avisoRecaladaService;
Into this:
#ManagedProperty("#{sigcueCertAvisoRecaladaService}")
private ISigcueCertAvisoRecaladaService sigcueCertAvisoRecaladaService;
Thanks to all of you for reading this and I hope this helps to similar problems in the future

Related

Spring #Transaction not rolling back

I have a very strange problem and looking for the solution here. I spent significant amount of time by reading articles and other questions on SO however no luck.
I am using #Transactional annotation in my sample application of Spring 3 and hibernate 3 as shown below. In the last line of method I am explicitly throwing NullPointerException as shown below.
package com.mkyong.common;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.mkyong.stock.bo.StockBo;
import com.mkyong.stock.model.Stock;
#Service("stockService")
public class StockServiceImpl {
final static Logger logger = Logger.getLogger(StockServiceImpl.class);
#Transactional(rollbackFor ={ NullPointerException.class} )
public void createNewStock(StockBo stockBo) {
/** insert **/
Stock stock = new Stock();
String code = "xee";
stock.setStockCode(code);
stock.setStockName(code);
stockBo.save(stock);
logger.debug("#################### After Save ##########################");
throw new NullPointerException();
}
}
However this transaction is not rolling back and always commiting to database even though NullPointerException is thrown.
Below is my application context file
<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:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
">
<!-- Database Configuration -->
<import resource="../database/DataSource.xml" />
<import resource="../database/Hibernate.xml" />
<tx:annotation-driven transaction-manager="transactionManager"/>
<!-- Auto scan the components -->
<context:component-scan base-package="com.mkyong.stock" />
<bean
class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
id="transactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
</beans>
Judging from your configuration you are using Hibernate, however you are using the transaction manager that is solely for plain JDBC usage.
To have proper transaction management you must use the PlatformTransactionManager which belongs to your persistence technology. In your case you should use the HibernateTransactionManager instead of the DataSourceTransactionManager.
<bean id="transactionManager" class="org.springframework.hibernate5.HibernateTransactionManager>
<property name="sessionFactory" ref="sessionFactory" />
</bean>
Note: This is for Hibernate5 (see the package name) use the one that fits your version of hibernate.
Make sure that the class that contains the method is in the application context not in the web application context (simple: the parent class of the method should be a service, repository etc. not a controller).
Also check that you import the #Transactional annotation from the right spring package.
Using only #Transactional annotation is enough. You dont require rollbackFor attribute to rollback on NullPointerException. Transactions with #Transactional annotation are defaulted to RuntimeException.
You should add rollbackFor only if you want to rollback on Checked Exceptions.

Combination of scope-proxy and parent

Hi I have the following short code :
https://github.com/shmuel-buchnik/scope-issue
I am getting the following error :
"Invalid property 'targetBeanName' of bean class [C]: Bean property 'targetBeanName' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?"
I will be happy to understand way .
Thanks in advance.
Adding context file to save access to github
<?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 http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean name="a" class="A">
<property name="action" ref="c"/>
</bean>
<bean name="b" class="B" scope="prototype">
<property name="d" ref="d"/>
<aop:scoped-proxy proxy-target-class="false"/>
</bean>
<bean name="c" class="C" parent="b" scope="prototype">
<aop:scoped-proxy proxy-target-class="false"/>
</bean>
<bean name="d" class="D"/>
</beans>
Well after debugging this is the issue :
When you define a parent in spring that means that you want to inherit parent bean configuration.
When you define scope proxy the proxy bean holds two properties targetBeanName and ProxyTargetClass.
When you inherit a bean that is a scoped proxy you get those properties as part of merging parent bean configuration .Then your bean try to find a setter for setting property and raise exception.
This means that in our example even if c was not scoped proxy we were still get the exception.
You cannot use a bean definition as a parent if the bean definition is configured as an <aop:scoped-proxy>.
Thus, just delete the <aop:scoped-proxy> declaration for the b bean, and it will work.

Having to use deprecated classes with Spring MVC

Have been trial Spring Web MVC (4.2.5) and have his a number of issues trying to use a DispatcherServlet and
<mvc:annotation-driven />
Have setup a simple #Controller class and wanted to use the POJO to JSON mapping. The docu said that if Jackson was detected on the class path it would be used automatically, however this didn't work for me and I was forced to use the 'deprecated' AnnotationMethodHandlerAdapter
<bean name="mappingJackson2HttpMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" />
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" >
<property name="messageConverters" ref="mappingJackson2HttpMessageConverter"/>
</bean>
which then worked fine.
Equally, tried to create a #ControllerAdvice class for handling all exceptions, but only got an #ExceptionHandler method working on the same controller class, and that was only when I added the (again) deprecated AnnotationMethodHandlerExceptionResolver to the context.
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver" />
Having to instantiate two deprecated classes suggests I am doing something wrong, especially when all the tutorials seem to suggest this should all 'just work', but I cannot see what (and indeed nosing through the Spring source I cannot see how the default and recommended handlers would work anyway)
There are no errors, the annotation simply aren't detected. The fill context xml is
please find the entire context XML below (is very simple)
<?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:p="http://www.springframework.org/schema/p"
xmlns:mvc="http://www.springframework.org/schema/mvc"
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
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<mvc:annotation-driven enable-matrix-variables="true"/>
<bean name="mappingJackson2HttpMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" />
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" >
<property name="messageConverters" ref="mappingJackson2HttpMessageConverter"/>
</bean>
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver" />
<context:component-scan base-package="com.domain.datastore.dao"/>
<context:component-scan base-package="com.domain.service"/>
<context:component-scan base-package="com.domain.uiapi"/>
</beans>
An example controller is
#RestController("/place/*")
public class PlaceController {
private PlaceService placeService;
#Autowired
public PlaceController(PlaceService placeService) {
this.placeService = placeService;
}
#RequestMapping(path="/{id}", method = RequestMethod.GET)
public #ResponseBody Place getPlace(#PathVariable("id") long id, Model model) {
return placeService.getPlace(id);
}
}
and the cross-cutting exception handler is
#ControllerAdvice
public class GlobalExceptionController {
public GlobalExceptionController() {
System.out.println("GlobalExceptionController");
}
#ResponseStatus(HttpStatus.NOT_FOUND)
#ExceptionHandler(NotFoundException.class)
public ModelAndView handleCustomException(NotFoundException ex) {
return null;
}
}
The issue was that Spring MVC was matching the path in
#RestController("/place/*")
And as such passing the instance of PlaceController around as the handler. The ExceptionHandlerExceptionResolver expects a HandlerMethod and so was unable to process the exception.
As such dropping the path from the class annotation and putting the full path in the method got it all working and I dropped all the deprecated beans.
#RestController
public class PlaceController {
#RequestMapping(path="/place/{id}", method = RequestMethod.GET)
public #ResponseBody Place getPlace(#PathVariable("id") long id, Model model)
What I am not sure is if this is a bug. Shouldn't it be possible to put the 'base' path in the RestController annotation and the subpath in the RequestMapping?
As far as I can understand you don't want to use a deprecated class. AnnotationMethodHandlerAdapter is indeed Deprecated. As doc suggest you should use RequestMappingHandlerAdapter instead.
See here for the details.
And instead of AnnotationMethodHandlerExceptionResolver you can use ExceptionHandlerExceptionResolver.

#Autowired doesn't work if component-scan removed

I'm facing the problem, that the annotation #Autowired doesn't work anymore (in all Java classes that uses this annotation) if I remove the component-scan tag from config
<?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="efco.auth" />
here are some beans...
There is only one class in the efco.auth package, and this one has no relation to the following class EfcoBasketLogic.
and a class that uses #Autowired:
package efco.logic;
public class EfcoBasketLogic extends BasketLogicImpl {
#Autowired
private EfcoErpService erpService;
This Bean is defined in an other spring config file:
<bean id="BasketLogic" class="efco.logic.EfcoBasketLogic">
<property name="documentLogic" ref="DocumentLogic" />
<property name="stateAccess" ref="StateAccess" />
<property name="contextAccess" ref="ContextAccess" />
</bean>
As you can see, erpService is not defined. The other three properties are on BasketLogicImpl and have setters.
What I'm doing wrong?
As Tomasz says, you need <context:annotation-config/> for #Autowired to work. When you had <context:component-scan/>, it implicitly included annotation-config for you.
Adding either autowire="byType" or autowire="byName" to your bean declaration should do the job.

Spring bean not injected into CXF web service, Why?

I am writing a RESTful service (using CXF on JBoss) in which I have inject another class using Spring (Autowired). But the class is not getting injected and is null.
Web Service Interface and Class (Where injection needs to happen)
package com.company.project.web;
#Path("/myws")
public interface IMyWebService {
#POST
#Path("/doSomething")
#Consumes("application/json")
#Produces("application/json")
MyResponse doSomething(MyRequest myRequest)
}
#Service("myWebService")
public class MyWebService implements IMyWebService {
#Autowired
private IMyCore myCore;
public MyResponse doSomething(MyRequest myRequest) {
....
}
}
That which has to be injected
package com.company.project.biz;
public interface IMyCore {
MyResponse doSomething(MyRequest myRequest);
}
#Component("myCore")
public class MyCore implements IMyCore {
public MyResponse doSomething(MyRequest myRequest) {
.....
}
}
Beans.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:jaxws="http://cxf.apache.org/jaxws"
xmlns:jaxrs="http://cxf.apache.org/jaxrs"
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://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-http.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
<context:annotation-config />
<context:component-scan base-package="com.company.project"/>
<jaxrs:server id="myWebService" address="/">
<jaxrs:serviceBeans>
<bean class="com.company.project.web.MyWebService" />
</jaxrs:serviceBeans>
<jaxrs:extensionMappings>
<entry key="json" value="application/json" />
</jaxrs:extensionMappings>
</jaxrs:server>
</beans>
My service is active (http://localhost:8080/{warname}/myws/doSomething) but the MyCore instance is not being injected into MyWebService (in the myCore field). It is always null and my service does not work as expected, instead throws NullPointerException
Tried all inputs gathered over google. No luck! Your help is highly appreciated.
Regards
Try to add below method to your web service:
#PostConstruct
public void init() {
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
}
The current web application context (usually the one loaded by ContextLoaderListener) will be used for autowiring, so the IMyCore bean has to be defined in the context listener configuration file and not in the web service one.
If you want to use Spring Beans in CXF Web Service class, then declare WebService as following in the XML configuration file of the CXF (e.g. spring-cxf.xml)
<bean id="hello" class="demo.spring.service.HelloWorldImpl" />
<jaxws:endpoint id="helloWorld" implementor="#hello" address="/HelloWorld" />
Declare separated bean for the WebService class and then put it in the endpoint with an ID. Like this you will have spring managed bean, where you can use AutoWired annotations as well.
Your beans never won't be injected automatically if you will declare your web service as following.
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml"/>
<import resource="classpath:META-INF/cxf/cxf-servlet.xml"/>
<jaxws:endpoint id="helloWorld" implementor="demo.spring.service.HelloWorldImpl" address="/HelloWorld"/>
In this case you will need either:
Inject spring beans manually
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
Or retrieve the beans one by one from the spring context
ApplicationContext context = ...; // your Spring ApplicationContext
HelloBean helloBean = (HelloBean) context.getBean("bean");
I haven't tried this for JAX-RS, but the approach in my opinion should be the same.
From CXF official documentation.
Try to add below bean configuration at Beans.xml
<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"/>
In my case, it worked..

Resources