Dale
Dale

Reputation: 1301

Unexpected UnsupportedOperationException on Hibernate validation failure

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)

Upvotes: 3

Views: 16767

Answers (5)

busitech
busitech

Reputation: 160

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();
    }
}

Upvotes: 2

Legna
Legna

Reputation: 1661

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 );
    }
}

Upvotes: 0

Aadil
Aadil

Reputation: 51

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.

Upvotes: 0

Dale
Dale

Reputation: 1301

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

Upvotes: 4

Hardy
Hardy

Reputation: 19119

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

Upvotes: 0

Related Questions