In autowiring byType if the property type is matched with more than one bean then it would throw an exception, but I can't see any exception when I am using the annotation #Autowired and defined two beans with same property type.
Below is the code:
Employee.java:
public class Employee {
private int id;
private String name;
private int salary;
// Getter and Setter
}
Dept:
public class Dept {
#Autowired
private Employee emp;
public Employee getEmp() {
return emp;
}
public void setEmp(Employee emp) {
this.emp = emp;
}
#Override
public String toString() {
return emp.getName();
}
}
Beans.xml:
<bean id = "dept" class = "Dept"></bean>
<bean id = "emp" class = "Employee">
<property name="id" value="25"></property>
<property name="name" value="Ram"></property>
<property name="salary" value="32000"></property>
</bean>
<bean id = "emp1" class = "Employee">
<property name="id" value="25"></property>
<property name="name" value="Sanju"></property>
<property name="salary" value="32000"></property>
</bean>
AppMain.java:
public class AppMain {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
Dept d = (Dept)context.getBean("dept");
System.out.println(d);
}
}
Please correct me if I am doing any thing wrong in it.
Spring is matching the emp variable name; if your beans were emp1 and emp2 you'd get an exception (unless you add a #Qualifier to the #AutoWired field).
You have defined a variable named as "emp" of Employee class which is same as the bean with id as "emp".Because of this spring don't get confused understanding which bean it has to inject.and if you change the bean id from "emp" to something else you will get an unsatisfied bean dependency exception. read more here
Related
I am new to springs, so I was just trying to implement inheritance in spring.
Customer.java
public class Customer {
String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Country.java
public class Country {
String cname;
String city;
public String getCname() {
return cname;
}
public void setCname(String cname) {
this.cname = cname;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
}
Main.java
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String args[]){
ApplicationContext context = new ClassPathXmlApplicationContext("Bean1.xml");
Customer cus = (Customer) context.getBean("customer");
System.out.println(cus.getName());
Country con = (Country) context.getBean("country");
System.out.println(con.getCname());
}
}
Bean1.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">
<bean id = "customer" class = "Customer">
<property name = "name" value = "Garima"/>
</bean>
<bean id ="country" class="Country" parent="customer">
<property name = "cname" value = "India"/>
<property name = "city" value = "Delhi"/>
</bean>
</beans>
Every time I run this without parent in Bean1.xml, this is running fine. As soon as I add parent , I receive the below mentioned error.
Error : Invalid property name of bean class [Country]: Bean property name is not writable or has an invalid setter method. Did you mean cname?
I have noticed this case with many other examples as well.
Can someone please help me with this?
This is because your bean definition suggests that Customer is parent of Country but your class Country doesn't extend Customer
<bean id ="country" class="Country" parent="customer">
So you have two options
Either remove parent="customer" from your bean definition
OR Extend Customer in Country class like
public class Country extends Customer{...
I am trying to use #Autowired Annotation in Spring for Dependency Injection
through a simple program but i give me following error
Exception in thread "main" java.lang.NullPointerException
at Customer.d(Customer.java:8)
at Main.main(Main.java:12)
Through xml configuration it give me correct result.
My xml 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 class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
<bean id="person" class="Person">
<property name="name" value="khan"/>
</bean>
<bean id="cust" class="Customer"></bean>
</beans>
Customer Class
public class Customer {
#Autowired
private Person p;
public void display(){
System.out.println(p.getName());
}
}
Person Class
public class Person {
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
private String name;
}
Main Class
public class Main {
public static void main(String[] a) {
Resource r=new ClassPathResource("SpringXml.xml");
BeanFactory factory=new XmlBeanFactory(r);
Customer c=(Customer)factory.getBean("cust");
c.display();
}
}
Try like this
public static void main(String[] args) throws Exception {
ApplicationContext context= new ClassPathXmlApplicationContext("SpringXml.xml");
Customer c = (Customer) context.getBean("cust");
c.display();
}
try this :
<bean id="person" class="com.yourpackage.Person">
<property name="name" value="khan"/>
</bean>
<bean id="cust" class="com.yourpackage.Customer">
<property name="p" ref="person"/>
</bean>
dont forget to add your fullpath class package
I have following bean class. I want to define this bean into the xml file.
I want to know which objects of this bean are added as a property of the bean in the xml?
public class Mybean{
public String name;
public String address;
public String getName()
{
return name;
}
public void setName(String name)
{
this.name=name;
}
public String getAddress()
{
return address;
}
}
Since you have getters and setters for the name and address fields they can both serve as properties.
<bean id="mybean" class="package.to.MyBean">
<property name="name" value="something"/>
<property name="address" value="something"/>
</bean>
Reference: http://www.springbyexample.org/examples/intro-to-ioc-basic-setter-injection.html
Let your class implement InitializingBean, then in the afterPropertiesSet() method, you can check which property has been set by spring
i m new to spring. i want to retrieve some field of user details from ldap and display on the jsp page. how can i retrieve this filed from ldap on page load?
<?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="contextSource"
class="org.springframework.ldap.core.support.LdapContextSource">
<property name="url" value="ldap://url:389" />
<property name="base" value="dc" />
<property name="userName" value="uid=admin,ou=system" />
<property name="password" value="secret" />
</bean>
<bean id="ldapTemplate" class="org.springframework.ldap.core.LdapTemplate">
<constructor-arg ref="contextSource" />
</bean>
<bean id="ldapContact"
class="org.LDAPContactDAO">
<property name="ldapTemplate" ref="ldapTemplate" />
</bean>
</beans>
It give me following exception
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'ldapContact' defined in class path resource [springldap.xml]: Cannot resolve reference to bean 'ldapTemplate' while setting bean property 'ldapTemplate'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'ldapTemplate' defined in class path resource [springldap.xml]: Cannot resolve reference to bean 'contextSource' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'contextSource' defined in class path resource [springldap.xml]: Error setting property values; nested exception is org.springframework.beans.NotWritablePropertyException: Invalid property 'userName' of bean class [org.springframework.ldap.core.support.LdapContextSource]: Bean property 'userName' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:328)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:106)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1325)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1086)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
at org.SpringFrameworkLDAPClient.main(SpringFrameworkLDAPClient.java:20)
I have write down some class file
package org;
public class ContactDTO {
private String displayName;
// lastName = Person.sn
private String firstName;
private String company;
private String department;
public String getDisplayName() {
return displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
public String getDepartment() {
return department;
}
public void setDepartment(String department) {
this.department = department;
}
public String toString() {
StringBuffer contactDTOStr = new StringBuffer("Person=[");
contactDTOStr.append(" firstName = " + firstName);
contactDTOStr.append(" ]");
return contactDTOStr.toString();
}
}
//interface ContactDAO
package org;
import java.util.List;
public interface ContactDAO {
public List getAllContactNames();
/*public List getContactDetails(String commonName);*/
}
// LDAPContactDAO
package org;
import java.util.List;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
public class LDAPContactDAO implements ContactDAO{
#Override
public List getAllContactNames() {
// TODO Auto-generated method stub
return null;
}
/*public List getContactDetails(String objectclass){
AndFilter andFilter = new AndFilter();
andFilter.and(new EqualsFilter("objectClass",objectclass));
System.out.println("LDAP Query " + andFilter.encode());
return ldapTemplate.search("", andFilter.encode(),new ContactAttributeMapper());
}*/
}
package org;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.dao.DataAccessException;
public class SpringFrameworkLDAPClient {
public static void main(String[] args) {
//Resource resource = new ClassPathResource("/SpringLDAPClient/src/com/javaworld/sample/springldap.xml");
//System.out.println(resource.toString());
try {
Resource resource = new ClassPathResource("springldap.xml");
BeanFactory factory = new XmlBeanFactory(resource);
System.out.println(factory.toString() + "\n");
ContactDAO ldapContact = (LDAPContactDAO)factory.getBean("ldapContact");
/*List contactList = ldapContact.getContactDetails("30662");*/
//List contactList =ldapContact.getAllContactNames();
//System.out.println(contactList.size());
/*int count = 0;
for( int i = 0 ; i < contactList.size(); i++){
System.out.print("Email: " + ((ContactDTO) contactList.get(i)).getMail() + " ");
System.out.println("SAP: " + ((ContactDTO) contactList.get(i)).getSap());
count++;
}
System.out.println("\n" + count);
*/
} catch (DataAccessException e) {
System.out.println("Error occured " + e.getCause());
}
}
}
But i am not able display this user details on jsp page? please any body know about this reply
The important part of the error message is:
Error creating bean with name 'contextSource'
defined in class path resource [springldap.xml]:
Error setting property values;
nested exception is org.springframework.beans.NotWritablePropertyException:
Invalid property 'userName'
of bean class [org.springframework.ldap.core.support.LdapContextSource]:
Bean property 'userName' is not writable or has an invalid setter method.
Does the parameter type of the setter match the return type of the getter?
I don't know wich version of Spring LDAP You're using, but userName seems to be deprecated in version 1.2 and completely removed in version 1.3 - try userDn instead, and see reference section on DirContext Authentication
And on how to get user details from LDAP try the reference: User Authentication using Spring LDAP
Or even better: use Spring Security with LDAP Authentication.
I'm trying to setup Spring using Hibernate and JPA, but when trying to persist an object, nothing seems to be added to the database.
Am using the following:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="url" value="${jdbc.url}"/>
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="persistenceUnitName" value="BankingWeb" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="generateDdl" value="true" />
<property name="showSql" value="true" />
<property name="databasePlatform" value="${hibernate.dialect}" />
</bean>
</property>
</bean>
<tx:annotation-driven/>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
<bean name="accountManager" class="ssel.banking.dao.jpa.AccountManager" />
<bean name="userManager" class="ssel.banking.dao.jpa.UserManager" />
And in AccountManager, I'm doing:
#Repository
public class AccountManager implements IAccountManager {
#PersistenceContext private EntityManager em;
/* -- 8< -- Query methods omitted -- 8< -- */
public Account storeAccount(Account ac) {
ac = em.merge(ac);
em.persist(ac);
return ac;
}
}
Where ac comes from:
Account ac = new Account();
ac.setId(mostRecent.getId()+1);
ac.setUser(user);
ac.setName(accName);
ac.setDate(new Date());
ac.setValue(0);
ac = accountManager.storeAccount(ac);
return ac;
Is there anyone who can point out what I'm doing wrong? The persist call returns without throwing exceptions. If afterwards I do em.contains(ac), this returns true.
In case anyone needed, here's how Account is defined:
#SuppressWarnings("serial")
#Entity
#NamedQueries({
#NamedQuery(name = "Account.AllAccounts", query = "SELECT a FROM Account a"),
#NamedQuery(name = "Account.Accounts4User", query = "SELECT a FROM Account a WHERE user=:user"),
#NamedQuery(name = "Account.Account4Name", query = "SELECT a FROM Account a WHERE name=:name"),
#NamedQuery(name = "Account.MaxId", query = "SELECT MAX(a.id) FROM Account a"),
#NamedQuery(name = "Account.Account4Id", query = "SELECT a FROM Account a WHERE id=:id"),
})
public class Account extends AbstractNamedDomain {
#Temporal(TemporalType.DATE)
#Column(name = "xdate")
private Date date;
private double value;
#ManyToOne(cascade={CascadeType.PERSIST, CascadeType.MERGE})
#JoinColumn(name="userid")
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
#OneToMany(cascade={CascadeType.PERSIST, CascadeType.MERGE}, fetch=FetchType.EAGER)
#OrderBy("date")
private List<AccountActivity> accountActivity = new ArrayList<AccountActivity>();
public List<AccountActivity> getAccountActivity() {
return accountActivity;
}
public void setAccountActivity(List<AccountActivity> accountActivity) {
this.accountActivity = accountActivity;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public double getValue() {
return value;
}
public void setValue(double value) {
this.value = value;
}
public void addAccountActivity(AccountActivity activity) {
// Make sure ordering is maintained, JPA only does this on loading
int i = 0;
while (i < getAccountActivity().size()) {
if (getAccountActivity().get(i).getDate().compareTo(activity.getDate()) <= 0)
break;
i++;
}
getAccountActivity().add(i, activity);
}
}
#MappedSuperclass public abstract class AbstractNamedDomain extends AbstractDomain {
private String name;
public AbstractNamedDomain() {
}
public AbstractNamedDomain(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
#MappedSuperclass public abstract class AbstractDomain implements Serializable {
#Id #GeneratedValue
private long id = NEW_ID;
public static long NEW_ID = -1;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public boolean isNew() {
return id==NEW_ID;
}
}
Thanks to eric and Juan Manuel's answers, I was able to figure out that the transaction wasn't committed.
Adding #Transactional to the storeAccount method did the trick!
I actually came across another way that this can happen.
In an injected EntityManager, no updates will ever occur if you have persistence.xml specified like this:
<persistence-unit name="primary" transaction-type="RESOURCE_LOCAL">
You need to remove the transaction-type attribute and just use the default which is JTA.
You do not explicitly need to call the persist method. The merge operation would write the changes to the DB upon commit.
Probably you're keeping the transaction active and it is not calling "commit" until other methods running supporting the active transaction end (all "voting" for commit and none for rollback.)
If you're sure that the entity you're going to persist is ok you could probably do this:
#TransactionManagement(TransactionManagementType.BEAN)
public class AccountManager implements IAccountManager { ..}
and manage your entity persistance adding:
#Resource
private SessionContext sessionContext;
public Account storeAccount(Account ac) {
sessionContext.getUserTransaction().begin();
ac = em.merge(ac);
em.persist(ac);
sessionContext.getUserTransaction().commit();
return ac;
}