Unexpected UnsupportedOperationException on Hibernate validation failure

折月煮酒 提交于 2019-11-26 21:43:02

问题


Why am I getting an UnsupportedOperationException from Hibernate upon validation failure? I'm hoping for a ConstraintViolationException.

Below is my DAO. When it passes validation it works fine. I'm using Hibernate and Hibernate Validator 4. I'm using Websphere 8.0. I think WebSphereExtendedJtaPlatform is the culprit, but I have no idea why.

If I look at what's supposedly the source code for WebSphereExtendedJtaPlatform (follow link for the source) it looks like most of the methods there just throw UnsupportedOperationException.

http://grepcode.com/file/repo1.maven.org/maven2/org.hibernate/hibernate-core/4.0.0.CR1/org/hibernate/service/jta/platform/internal/WebSphereExtendedJtaPlatform.java

Here is my stack trace:

org.hibernate.AssertionFailure <init> HHH000099: an assertion failure occured (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session): org.hibernate.AssertionFailure: null id in com.westfieldgrp.beanvalidation.persistence.Car entry (don't flush the Session after an exception occurs)
[11/14/12 16:48:48:785 EST] 00000020 RegisteredSyn E   WTRN0074E: Exception caught from before_completion synchronization operation: java.lang.UnsupportedOperationException
    at org.hibernate.service.jta.platform.internal.WebSphereExtendedJtaPlatform$TransactionManagerAdapter.setRollbackOnly(WebSphereExtendedJtaPlatform.java:139)

Another interesting snippet from my stack trace:

Entity manager factory name (src_persistence) is already registered.  If entity manager will be clustered or passivated, specify a unique value for property 'hibernate.ejb.entitymanager_factory_name'

Here is the class

package com.westfieldgrp.pom.data.dao;

import java.util.ArrayList;
import java.util.Set;

import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.RollbackException;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;

import com.westfieldgrp.beanvalidation.persistence.Car;
import com.westfieldgrp.beanvalidation.persistence.Driver;
import com.westfieldgrp.beanvalidation.persistence.Person;

public class CarDAO  {

    private EntityManager entityManager;


    public void save(Person convertedPerson, Driver convertedDriver, Car convertedCar, FacesContext facesContext) throws ConstraintViolationException{
    EntityManager em = getEntityManager();
    //em.setFlushMode(FlushModeType.COMMIT);

    if("test".equals(convertedPerson.getName())){       // To test JPA validation
        convertedPerson.setName(null);
    }
    //Person savedPerson =  em.merge(convertedPerson);
    try {
        //em.merge(convertedPerson);
        em.persist(convertedPerson);
        em.flush();
    } catch (Exception e) {
        System.out.println("*******" + getRootCause(e));
    }
    }

private String getRootCause(Throwable e){
    if(e.getCause() != null){
        return getRootCause(e.getCause());
    } else {
        return e.toString();
    }
}

    public EntityManager getEntityManager() {
            EntityManagerFactory emf = Persistence.createEntityManagerFactory("src_persistence");
            entityManager = emf.createEntityManager();
        return entityManager;
    }

    public void setEntityManager(EntityManager entityManager) {
        this.entityManager = entityManager;
    }
}

Person entity:

package com.westfieldgrp.beanvalidation.persistence;

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;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import org.hibernate.validator.constraints.Length;

/**
 * The persistent class for the PERSON database table.
 * 
 */
@Entity
@Table(name="PERSON")
public class Person implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    @Column(name="PERSON_ID")
    private int personId;

    @Column(name="NAME")
    @NotNull(message = "A name is required.")
    //@Length(min = 5, message = "Need a longer name.")
    private String name;

    @Column(name="EMAIL")
    @NotNull(message = "An email is required.")
    //@Pattern(regexp="[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?", message="Invalid email format.")
    private String email;

    public Person() {
    }

    public int getPersonId() {
        return this.personId;
    }

    public void setPersonId(int personId) {
        this.personId = personId;
    }

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getEmail() {
        return email;
    }

}

The whole stack trace:

[11/14/12 19:00:53:202 EST] 0000003c EntityManager Z org.hibernate.ejb.internal.EntityManagerFactoryRegistry addEntityManagerFactory HHH000436: Entity manager factory name (src_persistence) is already registered.  If entity manager will be clustered or passivated, specify a unique value for property 'hibernate.ejb.entitymanager_factory_name'
[11/14/12 19:00:53:214 EST] 0000003c SystemOut     O *******java.lang.UnsupportedOperationException
[11/14/12 19:00:53:214 EST] 0000003c AssertionFail Z org.hibernate.AssertionFailure <init> HHH000099: an assertion failure occured (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session): org.hibernate.AssertionFailure: null id in com.westfieldgrp.beanvalidation.persistence.Person entry (don't flush the Session after an exception occurs)
[11/14/12 19:00:53:215 EST] 0000003c RegisteredSyn E   WTRN0074E: Exception caught from before_completion synchronization operation: java.lang.UnsupportedOperationException
    at org.hibernate.service.jta.platform.internal.WebSphereExtendedJtaPlatform$TransactionManagerAdapter.setRollbackOnly(WebSphereExtendedJtaPlatform.java:139)
    at org.hibernate.engine.transaction.internal.jta.CMTTransaction.markRollbackOnly(CMTTransaction.java:131)
    at org.hibernate.engine.transaction.internal.TransactionCoordinatorImpl.setRollbackOnly(TransactionCoordinatorImpl.java:305)
    at org.hibernate.engine.transaction.synchronization.internal.SynchronizationCallbackCoordinatorImpl.setRollbackOnly(SynchronizationCallbackCoordinatorImpl.java:118)
    at org.hibernate.engine.transaction.synchronization.internal.SynchronizationCallbackCoordinatorImpl.beforeCompletion(SynchronizationCallbackCoordinatorImpl.java:108)
    at org.hibernate.engine.transaction.synchronization.internal.RegisteredSynchronization.beforeCompletion(RegisteredSynchronization.java:53)
    at org.hibernate.service.jta.platform.internal.WebSphereExtendedJtaPlatform$TransactionManagerAdapter$TransactionAdapter$1.invoke(WebSphereExtendedJtaPlatform.java:176)
    at $Proxy56.beforeCompletion(Unknown Source)
    at com.ibm.ws.jtaextensions.SynchronizationCallbackWrapper.beforeCompletion(SynchronizationCallbackWrapper.java:66)
    at com.ibm.tx.jta.impl.RegisteredSyncs.coreDistributeBefore(RegisteredSyncs.java:291)
    at com.ibm.ws.tx.jta.RegisteredSyncs.distributeBefore(RegisteredSyncs.java:152)
    at com.ibm.ws.tx.jta.TransactionImpl.prePrepare(TransactionImpl.java:2332)
    at com.ibm.ws.tx.jta.TransactionImpl.stage1CommitProcessing(TransactionImpl.java:553)
    at com.ibm.tx.jta.impl.TransactionImpl.processCommit(TransactionImpl.java:1014)
    at com.ibm.tx.jta.impl.TransactionImpl.commit(TransactionImpl.java:948)
    at com.ibm.ws.tx.jta.TranManagerImpl.commit(TranManagerImpl.java:379)
    at com.ibm.tx.jta.impl.TranManagerSet.commit(TranManagerSet.java:181)
    at com.ibm.ejs.csi.TranStrategy.commit(TranStrategy.java:922)
    at com.ibm.ejs.csi.TranStrategy.postInvoke(TranStrategy.java:234)
    at com.ibm.ejs.csi.TransactionControlImpl.postInvoke(TransactionControlImpl.java:579)
    at com.ibm.ejs.container.EJSContainer.postInvoke(EJSContainer.java:4755)
    at com.westfieldgrp.ejb.EJSLocalNSLCarSessionBean_f700c086.save(EJSLocalNSLCarSessionBean_f700c086.java)
    at com.westfieldgrp.beans.CarBean.processCar(CarBean.java:35)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:60)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
    at java.lang.reflect.Method.invoke(Method.java:611)
    at org.apache.el.parser.AstValue.invoke(AstValue.java:262)
    at org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:278)
    at org.apache.myfaces.view.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:83)
    at javax.faces.component._MethodExpressionToMethodBinding.invoke(_MethodExpressionToMethodBinding.java:88)
    at org.apache.myfaces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:100)
    at javax.faces.component.UICommand.broadcast(UICommand.java:120)
    at javax.faces.component.UIViewRoot._broadcastAll(UIViewRoot.java:973)
    at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:275)
    at javax.faces.component.UIViewRoot._process(UIViewRoot.java:1285)
    at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:711)
    at org.apache.myfaces.lifecycle.InvokeApplicationExecutor.execute(InvokeApplicationExecutor.java:34)
    at org.apache.myfaces.lifecycle.LifecycleImpl.executePhase(LifecycleImpl.java:171)
    at org.apache.myfaces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:189)
    at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1147)
    at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:722)
    at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:449)
    at com.ibm.ws.webcontainer.servlet.ServletWrapperImpl.handleRequest(ServletWrapperImpl.java:178)
    at com.ibm.ws.webcontainer.filter.WebAppFilterManager.invokeFilters(WebAppFilterManager.java:1020)
    at com.ibm.ws.webcontainer.servlet.CacheServletWrapper.handleRequest(CacheServletWrapper.java:87)
    at com.ibm.ws.webcontainer.WebContainer.handleRequest(WebContainer.java:883)
    at com.ibm.ws.webcontainer.WSWebContainer.handleRequest(WSWebContainer.java:1659)
    at com.ibm.ws.webcontainer.channel.WCChannelLink.ready(WCChannelLink.java:195)
    at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleDiscrimination(HttpInboundLink.java:452)
    at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleNewRequest(HttpInboundLink.java:511)
    at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.processRequest(HttpInboundLink.java:305)
    at com.ibm.ws.http.channel.inbound.impl.HttpICLReadCallback.complete(HttpICLReadCallback.java:83)
    at com.ibm.ws.tcp.channel.impl.AioReadCompletionListener.futureCompleted(AioReadCompletionListener.java:165)
    at com.ibm.io.async.AbstractAsyncFuture.invokeCallback(AbstractAsyncFuture.java:217)
    at com.ibm.io.async.AsyncChannelFuture.fireCompletionActions(AsyncChannelFuture.java:161)
    at com.ibm.io.async.AsyncFuture.completed(AsyncFuture.java:138)
    at com.ibm.io.async.ResultHandler.complete(ResultHandler.java:204)
    at com.ibm.io.async.ResultHandler.runEventProcessingLoop(ResultHandler.java:775)
    at com.ibm.io.async.ResultHandler$2.run(ResultHandler.java:905)
    at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1648)

回答1:


I ended up modifying the WebSphereExtendedJtaPlatform code according to the following link. I am so baffled why that class was essentially not implemented.

https://forum.hibernate.org/viewtopic.php?f=1&t=992310




回答2:


I had the same problem on Websphere Liberty 16.0.0.4, and solved it with a change to persistence.xml:

<property name="hibernate.transaction.jta.platform" value="biz.bitech.hibernate.websphere.WebSphereJtaPlatform" />

The following class needs to be in the classpath along with the hibernate libs:

package biz.bitech.hibernate.websphere;

import javax.transaction.TransactionManager;
import javax.transaction.UserTransaction;

import com.ibm.tx.jta.TransactionManagerFactory;
import com.ibm.tx.jta.UserTransactionFactory;
import org.hibernate.engine.transaction.jta.platform.internal.AbstractJtaPlatform;

public class WebSphereJtaPlatform extends AbstractJtaPlatform {

    @Override
    protected TransactionManager locateTransactionManager() {
        return TransactionManagerFactory.getTransactionManager();
    }

    @Override
    protected UserTransaction locateUserTransaction() {
        return UserTransactionFactory.getUserTransaction();
    }
}



回答3:


You create a new entity manager on each request using getEntityManager(). You should request (eg via dependency injection) the application wide persistence manager.




回答4:


Please note that you are recieving the HHH000099 error from hibernate. This is due to the GeneratedValue returning null and when hibernate does an insert, it passes a null to your PK.

I take it that your ID is auto incremented withing the table. When you set Generated value to AUTO/TABLE/IDENTITY, Hibernate looks for the value in the table. It shouldnt be a problem if you persist the table.

I had a similar issue and all i did was make the column as insertable=false.

Hope that helps.




回答5:


the code below is from hibernate-core 4.3.7.FINAL (SynchronizationCallbackCoordinatorNonTrackingImpl)

you will see a call to setRollbackOnly just before the exception is re-package and sent, for WebSphereExtendedJtaPlatform it simply throws an unsupported operation exception, which is what you see on the logs. At this point, as you never reach the point where your runtime exception is re-packaged, it is lost.

But somehow hibernate manages to log it out to the stdout, so you will find your SQL exception in your SystemOut.log file

@Override
public void beforeCompletion() {
    LOG.trace( "Transaction before completion callback" );

    if ( !transactionCoordinator.isActive() ) {
        return;
    }

    boolean flush;
    try {
        final int status = transactionCoordinator.getTransactionContext().getTransactionEnvironment()
                .getJtaPlatform().getCurrentStatus();
        flush = managedFlushChecker.shouldDoManagedFlush( transactionCoordinator, status );
    }
    catch ( SystemException se ) {
        setRollbackOnly();
        throw exceptionMapper.mapStatusCheckFailure(
                "could not determine transaction status in beforeCompletion()", se );
    }

    try {
        if ( flush ) {
            LOG.trace( "Automatically flushing session" );
            transactionCoordinator.getTransactionContext().managedFlush();
        }
    }
    catch ( RuntimeException re ) {
        setRollbackOnly();
        throw exceptionMapper.mapManagedFlushFailure( "error during managed flush", re );
    }
    finally {
        transactionCoordinator.sendBeforeTransactionCompletionNotifications( null );
        transactionCoordinator.getTransactionContext().beforeTransactionCompletion( null );
    }
}


来源:https://stackoverflow.com/questions/13388069/unexpected-unsupportedoperationexception-on-hibernate-validation-failure

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!