Combination of scope-proxy and parent - spring

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.

Related

Problem with spring defined #ManagedProperty

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

Creating a repository instance in Spring Data

I'm new to Spring Data and to Spring in general, so don't be hard on me.
I can't find a way to instantiate a repository. I read the documentation:
http://docs.spring.io/spring-data/data-solr/docs/1.0.0.RC1/reference/htmlsingle/#repositories.create-instances
It describes different ways of declaring repositories (xml, filters, etc), but doesn't say how I can get an instance of it in my code.
Here is my configuration 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:solr="http://www.springframework.org/schema/data/solr"
xsi:schemaLocation="http://www.springframework.org/schema/data/solr http://www.springframework.org/schema/data/solr/spring-solr-1.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<solr:repositories base-package="spring" />
<solr:solr-server id="solrServer" url="http://localhost:8983/solr" />
<bean id="taskRepo" class="spring.SolrTaskRepository">
</bean>
<bean id="solrTemplate" class="org.springframework.data.solr.core.SolrTemplate">
<constructor-arg index="0" ref="solrServer"/>
</bean>
</beans>
And SolrTaskRepository:
public interface SolrTaskRepository<T, ID extends Serializable> extends SolrCrudRepository<T, ID> {
Page<T> findByOrigin(String origin, Pageable page);
}
Could someone help me out?
If you want to use the repo(or any spring bean) somewhere out of the context:
ApplicationContext context = new ClassPathXmlApplicationContext(
"applicationContext.xml");
MyRepo obj = (MyRepo) context.getBean("myRepo");
If you use the repo in some other bean managed by spring(some service) you can autowire it
#Autowire
private MyRepo myRepo;// + setter
or inject it in the context:
<bean id="someService" class="com.org.core.SomeService">
<property name="myRepo" ref="myRepo" />
</bean>
For both ways you need the bean defined in the context:
<bean id="myRepo" class="com.org.core.MyRepo">
</bean>
Example context file:
<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-2.5.xsd">
<bean id="myRepo" class="com.org.core.MyRepo">
</bean>
</beans>
IF you load the context with ClassPathXmlApplicationContext you need the file in the classpath.

Spring bean profile reference

I started using bean profile for conditional bean creation, but When i use the profiled bean outside of profile with ref I get exception nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'pb' is defined
<bean id="q" class="com.Q"> //spring can not create this bean since it depends on `pb` bean which is profiled.
<property name="p" ref="pb"/>
</bean>
<beans profile="a">
<bean id="pb" class="com.T"/>
</beans>
<beans profile="b">
<bean id="pb" class="com.T"/>
</beans>
How can I achieve this? I am sure a profile is on:
System.setProperty(AbstractEnvironment.DEFAULT_PROFILES_PROPERTY_NAME, "a");
System.setProperty(AbstractEnvironment.ACTIVE_PROFILES_PROPERTY_NAME, "a");

Attribute "value" must be declared for element type "constructor-arg"

I am new to the Spring framework. While trying constructor DI I am getting this exception.
Exception in thread "main" org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException: Line 7 in XML document from class path resource [spring.xml] is invalid; nested exception is org.xml.sax.SAXParseException: Attribute "vlaue" must be declared for element type "constructor-arg".
Here by spring.xml file for your reference.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN"
"http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
<bean id="kaka" class="com.spring.test.FootballPlayer">
<constructor-arg type="int" vlaue="7"/>
</bean>
<bean id="forlan" class="com.spring.test.FootballPlayer">
<constructor-arg value="10"/>
</bean>
<bean id="predator" class="com.spring.test.Predator"/>
</beans>
Shall we use both constructor-arg and property tags for a same bean?
Please correct following:
<bean id="kaka" class="com.spring.test.FootballPlayer">
<constructor-arg type="int" vlaue="7"/>
</bean>
to
<bean id="kaka" class="com.spring.test.FootballPlayer">
<constructor-arg type="int" value="7"/>
</bean>
Your spring XML is invalid cause of the typo in the kaka bean. This is what the error means!
You should replace vlaue with value.

#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.

Resources