I'm trying to apply formatter-annotation to the field "phone" in next model-class:
public class User {
#ContactNumberFormate
private String phone;
}
Interface for annotation:
#Target({ElementType.METHOD, ElementType.FIELD})
#Retention(RetentionPolicy.RUNTIME)
public #interface ContactNumberFormate {
}
Formatter:
#Component
public class PhoneFormatter implements Formatter<String> {
#Override
public String parse(String phoneNum, Locale locale) throws ParseException {
phoneNum = phoneNum.trim();
String regex = "^\\(?(\\+*1)?[-.\\s*]?([0-9]{3})\\)?[-.\\s*]?([0-9]{3})[-.\\s*]?([0-9]{4})$";
Pattern.compile(regex).matcher(phoneNum);
return phoneNum;
}
#Override
public String print(String phone, Locale locale) {
return phone;
}
}
Annotation-factory:
public class PhoneFormatAnnotationFormatterFactory implements
AnnotationFormatterFactory<ContactNumberFormate> {
#Override
public Set<Class<?>> getFieldTypes() {
return Collections.singleton(String.class);
}
#Override
public Printer<?> getPrinter(ContactNumberFormate contactNumberFormate, Class<?> aClass) {
return new PhoneFormatter();
}
#Override
public Parser<?> getParser(ContactNumberFormate contactNumberFormate, Class<?> aClass) {
return new PhoneFormatter();
}
}
FormatterRegistrar:
public class ApplicationFormatterRegister implements FormatterRegistrar {
#Override
public void registerFormatters(FormatterRegistry formatterRegistry) {
formatterRegistry.addFormatterForFieldAnnotation(new PhoneFormatAnnotationFormatterFactory());
}
}
config:
<mvc:annotation-driven conversion-service="conversionService">
<mvc:message-converters>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper" ref="objectMapper"/>
</bean>
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
<bean id="applicationConversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="formatterRegistrars">
<set>
<ref bean="applicationFormatterRegistrar"/>
</set>
</property>
</bean>
<bean id="applicationFormatterRegistrar" class="ru.spb.dreamwhite.util.phoneUtil.ApplicationFormatterRegister"/>
And it does not work: phone-values saved in database, but in non-formatted form.
Note: when I run test in debug with breakpoint on PhoneFormatter, test passes susseccfully. That means, that my Formatter is out of process. But when I set breakpoint on PhoneFormatAnnotationFormatterFactory.getFieldTypes, test interrupted.
In particular, debug with breakpoint on return Collections.singleton(String.class); in
public Set<Class<?>> getFieldTypes() {
return Collections.singleton(String.class);
}
shows that the class PhoneFormatAnnotationFormatterFactory has no fields...
Related
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 am currently trying to integrate hibernate with spring.I am using the dao design pattern and mysql as database. i am trying to add the contacte entity in the db but it's not added and no error was displayed.By the way i can get the list of contact and get it by id but i can't update or insert.
this is my context 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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
">
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/mailmaneger" />
<property name="username" value="root" />
<property name="password" value="" />
<property name="defaultAutoCommit" value="false" />
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="mysessionFactory" />
</bean>
<bean id="mysessionFactory"
class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="packagesToScan" value="biz.picosoft.entity"/>
<property name="dataSource" ref="dataSource"></property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<bean id="template" class="org.springframework.orm.hibernate5.HibernateTemplate">
<property name="sessionFactory" ref="mysessionFactory"></property>
<property name="checkWriteOperations" value="false"></property>
</bean>
<bean id="d" class="biz.picosoft.daoImpl.ContacteDaoImpl">
<property name="template" ref="template"></property>
</bean>
</beans>
generic dao file
package biz.picosoft.daoImpl;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import org.springframework.orm.hibernate5.HibernateTemplate;
import org.springframework.transaction.annotation.Transactional;
import dao.GenericDao;
#Transactional(readOnly = false)
public class GenericDaoImp<T> implements GenericDao<T> {
HibernateTemplate template;
protected Class<T> daoType;
public GenericDaoImp() {
Type t = getClass().getGenericSuperclass();
ParameterizedType pt = (ParameterizedType) t;
daoType = (Class) pt.getActualTypeArguments()[0];
}
public HibernateTemplate getTemplate() {
return template;
}
public void setTemplate(HibernateTemplate template) {
this.template = template;
}
public void insert(T t) {
// TODO Auto-generated method stub
template.save(t);
}
public void update(T t) {
// TODO Auto-generated method stub
template.update(t);
}
public void delete(T t) {
// TODO Auto-generated method stub
template.delete(t);
}
public T findById(Class<T> t, String id) {
// TODO Auto-generated method stub
return template.get(t, id);
}
public List<T> findAll() {
// TODO Auto-generated method stub
return template.loadAll(daoType);
}
}
contacte dao file
package dao;
import biz.picosoft.entity.Contacte;
public interface ContacteDao extends GenericDao<Contacte> {
}
contactedaoimpl
package biz.picosoft.daoImpl;
import org.springframework.transaction.annotation.Transactional;
import biz.picosoft.entity.Contacte;
import dao.ContacteDao;
#Transactional(readOnly = false)
public class ContacteDaoImpl extends GenericDaoImp<Contacte> implements ContacteDao {
}
the entity
package biz.picosoft.entity;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name = "Contacte")
public class Contacte implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "idContact")
int idContact;
#Column(name = "nom")
String nom;
#Column(name = "mail")
String mail;
#Column(name = "téléphone")
String téléphone;
#Column(name = "adresse")
String adresse;
public Contacte() {
super();
}
public Contacte(String nom, String mail, String téléphone, String adresse) {
super();
this.nom = nom;
this.mail = mail;
this.téléphone = téléphone;
this.adresse = adresse;
}
public long getIdContact() {
return idContact;
}
public void setIdContact(int idContact) {
this.idContact = idContact;
}
public String getNom() {
return nom;
}
public void setNom(String nom) {
this.nom = nom;
}
public String getMail() {
return mail;
}
public void setMail(String mail) {
this.mail = mail;
}
public String getTéléphone() {
return téléphone;
}
public void setTéléphone(String téléphone) {
this.téléphone = téléphone;
}
public String getAdresse() {
return adresse;
}
public void setAdresse(String adresse) {
this.adresse = adresse;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (int) (idContact ^ (idContact >>> 32));
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Contacte other = (Contacte) obj;
if (idContact != other.idContact)
return false;
return true;
}
}
my main
package biz.picosoft.mains;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
import biz.picosoft.daoImpl.ContacteDaoImpl;
import biz.picosoft.entity.Contacte;
public class TestHibernate {
public static void main(String[] args) {
// TODO Auto-generated method stub
Contacte contacte = new Contacte("fatma", "test2", "test", "test");
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
contacte.setIdContact(4);
ContacteDaoImpl contacteDaoImpl = (ContacteDaoImpl) context.getBean("d");
contacteDaoImpl.insert(contacte);
}
}
you don't need to add #Transactional annotation on all DAO implementation, if you already added #Transactional annotation on GenericDaoImp, and other thing put #Transactional(readOnly = false) annotation on method on which method you only fetch the data. That's only suggestion and you problem will resolved after only
replace <property name="defaultAutoCommit" value="false" />
with <property name="defaultAutoCommit" value="true" />
I have tried that and its working for me.
The problem may be that you need to enable annotation support as well as transactions. Try adding the following to your spring xml:
<context:annotation-config/>
<tx:annotation-driven />
FYI you should also check out: Why HibernateTemplate isn't recommended?
I am trying to use annotated TX Spring support.
Application context XML:
<?xml ...>
<tx:annotation-driven/>
<bean id="dataSource" class="oracle.jdbc.pool.OracleDataSource">
...
</bean>
<bean id="repository" class="Repository">
<constructor-arg ref="dataSource"/>
</bean>
</beans>
Actual code:
public class Repository {
#Transactional
public void save(Op op) {
System.out.println("Transaction active:::: " + TransactionSynchronizationManager.isActualTransactionActive());
...
}
}
Calling code:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = {"/integration-context.xml"})
public class RepositoryTest {
#Autowired
private Repository repository;
#Test
public void testRepositoryPersistence() {
Op op = mock(Op.class);
repository.save(op);
}
}
And it gives FALSE.
What am I doing wrong?
You should add this in your configuration
<context:annotation-config/>
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
add an interface on your RepositoryClass
public class Repository implements IRepository{
#Transactional
public void save(Op op) {
System.out.println("Transaction active:::: " + TransactionSynchronizationManager.isActualTransactionActive());
...
}
}
and this in your test class
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = {"classpath:/integration-context.xml"})
#TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = false)
public class RepositoryTest extends AbstractTransactionalJUnit4SpringContextTests{
#Autowired
private IRepository repository;
#Test
public void testRepositoryPersistence() {
Op op = mock(Op.class);
repository.save(op);
}
}
see this tutorial.
//here I define all classes and interface which i used
//Service interface
public interface CustomerService {
public void addCustomer(CustomerTO cto);
}
//Service class implementation
public class CustomerServiceImpl implements CustomerService {
#Autowired
CustomerDAO cdao=null;
public void addCustomer(CustomerTO cto){
cdao.addCustomer(cto);
}
}
//CustomerTO Class
public class CustomerTO {
private int cid;
private String cname;
private String email;
private long phone;
private String city;
public CustomerTO(int cid, String cname, String email, long phone,
String city) {
this.cid = cid;
this.cname = cname;
this.email = email;
this.phone = phone;
this.city = city;
}
//Setter and Getters
public class JdbcCustomerDAO implements CustomerDAO {
#Autowired
JdbcTemplate jdbcTemp;
public void addCustomer(CustomerTO cto){
String sql="insert into customer values(?,?,?,?,?)";
Object ar[]={cto.getCid(),cto.getCname(),cto.getEmail(),cto.getPhone(),cto.getCity()};
jdbcTemp.update(sql,ar);
}
//Client COde
public class Lab24Client {
public static void main(String[] args) {
ApplicationContext ctc=new ClassPathXmlApplicationContext("applicationContext.xml");
CustomerService c=(CustomerService)ctc.getBean("cs");
//add Customer
CustomerTO cust=new CustomerTO(102,"vsa","vsa#gmail.com",6154,"Pune");
c.addCustomer(cust);
}
//CustomerDAO
public interface CustomerDAO {
public void addCustomer(CustomerTO cto);
}
//spring ApplicationContext.xml file
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<bean id="dataSource class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost/vik"/>
<property name="username" value="root"/>
</bean>
<bean id="jdbcTemp" class="org.springframework.jdbc.core.JdbcTemplate" autowire="constructor"/>
<bean id="cdao" class="com.jlc.JdbcCustomerDAO"/>
<bean id="cs" class="com.jlc.CustomerServiceImpl"/>
//CustomerRowMapper
public class CustomerRowMapper implements RowMapper<CustomerTO>{
#Override
public CustomerTO mapRow(ResultSet rs, int rn) throws SQLException {
CustomerTO cto=new CustomerTO();
cto.setCid(rs.getInt(1));
cto.setCname(rs.getString(2));
cto.setEmail(rs.getString(3));
cto.setPhone(rs.getLong(4));
cto.setCity(rs.getString(5));
return cto;
}
}
//when I am running the client i got following excpetion
Exception in thread "main" java.lang.NullPointerException
at com.spring.CustomerServiceImpl.addCustomer(CustomerServiceImpl.java:11)
at com.spring.Lab24Client.main(Lab24Client.java:12)
//Please tell me what mistake i did with code or what's the problem in following program
You have to enable/register annotation config like below code in your xml.
<context:annotation-config/>
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;
}