3

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)
Dale
  • 1,289
  • 3
  • 16
  • 36

5 Answers5

4

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

Dale
  • 1,289
  • 3
  • 16
  • 36
  • A small update for all those that are going to use the same class, on Websphere 8.5.5 is the package reference [code] uowManagerClass = Class.forName("com.ibm.wsspi.uow.UOWManager");[code] – javapapo Jun 16 '14 at 09:13
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();
    }
}
busitech
  • 151
  • 5
  • I replaced the dependency to com.ibm with reflection, it's working perfect now. My errors (validation) are shown in correct way and don't get the UnsupportedOperationException anymore. – Cuball Dec 21 '17 at 09:17
0

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

Hardy
  • 18,659
  • 3
  • 49
  • 65
  • Thanks. I'm new to this stuff. Could you expound on how to get the app wide manager? Also could I do this without using dependency injection? – Dale Nov 16 '12 at 15:10
  • It will depends on your technology stack? What else are you using? Spring? CDI? If you don't want to use dependency injection you can look up the entity manager via JNDI. – Hardy Nov 16 '12 at 15:58
0

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.

Aadil
  • 51
  • 3
0

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 );
    }
}
Legna
  • 1,632
  • 15
  • 15