I work with Spring MVC RESTful
app and get the ConstraintViolationException
while persisting. The error message provided below,
Exception in thread " STARTING" javax.validation.ConstraintViolationException: Validation failed for classes [mobi.puut.entities.WalletInfo] during persist time for groups [javax.validation.groups.Default, ]
List of constraint violations:[
ConstraintViolationImpl{interpolatedMessage='may not be null', propertyPath=id, rootBeanClass=class mobi.puut.entities.WalletInfo, messageTemplate='{javax.validation.constraints.NotNull.message}'}
ConstraintViolationImpl{interpolatedMessage='may not be null', propertyPath=currency, rootBeanClass=class mobi.puut.entities.WalletInfo, messageTemplate='{javax.validation.constraints.NotNull.message}'}
]
at org.hibernate.cfg.beanvalidation.BeanValidationEventListener.validate(BeanValidationEventListener.java:140)
at org.hibernate.cfg.beanvalidation.BeanValidationEventListener.onPreInsert(BeanValidationEventListener.java:80)
at org.hibernate.action.internal.EntityIdentityInsertAction.preInsert(EntityIdentityInsertAction.java:197)
at org.hibernate.action.internal.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:75)
at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:626)
at org.hibernate.engine.spi.ActionQueue.addResolvedEntityInsertAction(ActionQueue.java:280)
at org.hibernate.engine.spi.ActionQueue.addInsertAction(ActionQueue.java:261)
at org.hibernate.engine.spi.ActionQueue.addAction(ActionQueue.java:306)
at org.hibernate.event.internal.AbstractSaveEventListener.addInsertAction(AbstractSaveEventListener.java:318)
at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:275)
at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:182)
at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:113)
at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:189)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:132)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:58)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:780)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:765)
at mobi.puut.database.WalletInfoDao.create(WalletInfoDao.java:62)
at mobi.puut.database.WalletInfoDao$$FastClassBySpringCGLIB$$624213d.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:738)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:282)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:673)
at mobi.puut.database.WalletInfoDao$$EnhancerBySpringCGLIB$$a84b41b3.create(<generated>)
at mobi.puut.services.WalletService.createWalletInfo(WalletService.java:273)
at mobi.puut.services.WalletService.lambda$generateAddress$0(WalletService.java:97)
at mobi.puut.controllers.WalletManager$1.lambda$onSetupCompleted$0(WalletManager.java:109)
at java.lang.Iterable.forEach(Iterable.java:75)
at java.util.Collections$SynchronizedCollection.forEach(Collections.java:2062)
at mobi.puut.controllers.WalletManager$1.onSetupCompleted(WalletManager.java:109)
at org.bitcoinj.kits.WalletAppKit.startUp(WalletAppKit.java:325)
at com.google.common.util.concurrent.AbstractIdleService$2$1.run(AbstractIdleService.java:54)
at com.google.common.util.concurrent.Callables$3.run(Callables.java:95)
The project structure is provided below,
The sample code directed to the error proviced below,
@Transactional(rollbackFor = Exception.class)
public WalletInfo create(String name, String address) {
// create the WalletInfo entity with provided name and address
WalletInfo walletInfo = new WalletInfo();
walletInfo.setAddress(address);
walletInfo.setName(name);
// persist the created instance into the database
sessionFactory.getCurrentSession().persist(walletInfo);
return walletInfo;
}
protected WalletInfo createWalletInfo(final String walletName, final String address) {
return walletInfoDao.create(walletName, address);
}
public synchronized WalletInfo generateAddress(final String walletName, String currencyName) {
// get the WalletInfo entity from the database with the wallet and the currency name
WalletInfo walletInfo = walletInfoDao.getWalletInfoWithWalletNameAndCurrency(walletName, currencyName);
// generate wallet, if the wallet is not
// generated previously
if (walletInfo == null) {
if (genWalletMap.get(walletName) == null) {
logger.info("Wallet name that we are workign on {}", walletName);
final WalletManager walletManager = WalletManager.setupWallet(walletName);
walletManager.addWalletSetupCompletedListener((wallet) -> {
Address address = wallet.currentReceiveAddress();
/*at mobi.puut.services.WalletService.lambda$generateAddress$0(WalletService.java:97) */
WalletInfo newWallet = createWalletInfo(walletName, address.toString());
walletMangersMap.put(newWallet.getId(), walletManager);
genWalletMap.remove(walletName);
});
genWalletMap.put(walletName, walletManager);
}
return walletInfo;
}
return null;
}
private void setupWalletKit(final String walletId) {
File directory = getWalletDirectory(walletId);
// if the seed is not null, that means we are restoring from the backup
bitcoin = new WalletAppKit(networkParameters, directory, WALLET_FILE_NAME) {
@Override
protected void onSetupCompleted() {
// Don't make the user wait for confirmations
// they're sending their own money anyway!!
bitcoin.wallet().allowSpendingUnconfirmedTransactions();
Wallet wallet = bitcoin.wallet();
model.setWallet(wallet);
/* lambda$onSetupCompleted$0(WalletManager.java:109) */
setupCompletedListeners.forEach(listener -> listener.onSetupCompleted(wallet));
}
};
// some code
}
The WalletInfo
entity provided,
@Entity
@Table(name = "wallet_info")
public class WalletInfo {
@Id
@Column(name = "id")
// @NotNull
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotNull
@Column(name = "name")
private String name;
@NotNull
@Column(name = "address")
private String address;
@NotNull
@Column(name = "currency")
private String currency;
public Long getId() {
return id;
}
public WalletInfo(@NotNull String name, @NotNull String address, @NotNull String currency) {
this.name = name;
this.address = address;
this.currency = currency;
}
public WalletInfo(@NotNull String name, @NotNull String address) {
this.name = name;
this.address = address;
}
public WalletInfo() {
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getCurrency() {
return currency;
}
public void setCurrency(String currency) {
this.currency = currency;
}
}
What is the issue here and how to solve it?
The solution provided in the comment is correct, I just want to write it elaborately to help others, especially, who are using the Hibernate
newly. The WalletInfo
entity matches with the wallet_info
table in the MySQL
,
Notice that every entity is provided as non-null NN
and hence, needs to be matched while persisting
in the database.
The walletInfo
entity class after the modification,
@Entity
@Table(name = "wallet_info")
public class WalletInfo {
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotNull
@Column(name = "name")
private String name;
@NotNull
@Column(name = "address")
private String address;
@NotNull
@Column(name = "currency")
private String currency;
// getters and setters
// constructors
public WalletInfo(@NotNull String name, @NotNull String address, @NotNull String currency) {
this.name = name;
this.address = address;
this.currency = currency;
}
public WalletInfo(@NotNull String name, @NotNull String address) {
this.name = name;
this.address = address;
}
public WalletInfo() {
}
}
In the database layer, this was the method I was using to persist
,
@Transactional(rollbackFor = Exception.class)
public WalletInfo create(String name, String currency, String address) {
// create the WalletInfo entity with provided name and address
WalletInfo walletInfo = new WalletInfo();
walletInfo.setAddress(address);
walletInfo.setName(name);
walletInfo.setCurrency(currency);
// persist the created instance into the database
sessionFactory.getCurrentSession().persist(walletInfo);
return walletInfo;
}
I just added the currecny
column and hence, forget to add the
walletInfo.setCurrency(currency)
line which made the currency
as null
earlier and creates the error. I still can make the id
null as the this is not an element in the constructor with @NotNull
annotation and the entity parameter definition it was also not annotated with @NotNull
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
I hope this will help some people.
In case you are working with lombok, you might have forgotten the @Data
-Annotation over your entity class.
The reason why every attribute is null, while it shouldn't be, is that it's simply not possible for spring to write the data into your object, and therefore the exception occurs. No setters, no constructor => no data in your object, so the contents will always be null.
This is a very tricky thing, since you only get an exception when you validate your database entrys, without the Not-Null-Annotation, it just writes null into your fields, if that works out for all of them...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With