Constructor queries on a non-persistent entity unexpectedly fail to supply a Boolean parameter as a constructor argument
Asked Answered
L

0

2

There are two tables in MySQL database

  • user_table
  • feedback

The relationship between them is intuitive - one to many from user_table to feedback.


I need to fetch only a list of selected columns from these tables which are

  • From feedback
    • feedbackId (java.lang.Long)
    • feedbackTitle (java.lang.String)
    • feedbackDescription (String, decorated by @Lob)
    • feedbackDate (org.joda.time.DateTime)
    • testimonial (java.lang.Boolean)
  • From user_table
    • userId (java.lang.Long)
    • firstName (java.lang.String)

These many fields out of many others are required to get by executing a query.

The criteria query is as follows.

CriteriaBuilder criteriaBuilder=entityManager.getCriteriaBuilder();
CriteriaQuery<FeedbackUtils>criteriaQuery = criteriaBuilder.createQuery(FeedbackUtils.class);
Metamodel metamodel = entityManager.getMetamodel();
EntityType<Feedback> entityType = metamodel.entity(Feedback.class);
Root<Feedback> root = criteriaQuery.from(entityType);

List<Selection<?>>selections=new ArrayList<Selection<?>>();
selections.add(root.get(Feedback_.feedbackId));
selections.add(root.get(Feedback_.feedbackTitle));
selections.add(root.get(Feedback_.feedbackDescription));
selections.add(root.get(Feedback_.feedbackDate));
selections.add(root.get(Feedback_.testimonial));

Join<Feedback, UserTable> join = root.join(Feedback_.userId, JoinType.INNER);
selections.add(join.get(UserTable_.userId));
selections.add(join.get(UserTable_.firstName));

criteriaQuery.select(criteriaBuilder.construct(FeedbackUtils.class, selections.toArray(new Selection[0])));
criteriaQuery.orderBy(criteriaBuilder.desc(root.get(Feedback_.feedbackId)));

List<FeedbackUtils>list = entityManager.createQuery(criteriaQuery).setFirstResult(first).setMaxResults(pageSize).getResultList();

The FeedbackUtils class is as follows.

import java.io.Serializable;
import org.joda.time.DateTime;

public final class FeedbackUtils implements Serializable
{
    private static final long serialVersionUID = 1L;
    private Long feedbackId;
    private String feedbackTitle;
    private String feedbackDescription;
    private DateTime feedbackDate;
    private Boolean testimonial;    //This causes the exception
    private Long userId;
    private String firstName;

    public FeedbackUtils(Long feedbackId, String feedbackTitle, String feedbackDescription, DateTime feedbackDate, Boolean testimonial, Long userId, String firstName) {
        this.feedbackId = feedbackId;
        this.feedbackTitle = feedbackTitle;
        this.feedbackDescription = feedbackDescription;
        this.feedbackDate = feedbackDate;
        this.testimonial = testimonial;
        this.userId = userId;
        this.firstName = firstName;
    }

    //Getters and setters.
}

Mapping of testimonial property in the Feedback entity is as follows.

@Column(name = "testimonial")
private Boolean testimonial;

It is a type of TINYINT(1) in MySQL.


The above query when attempted causes the following exception to be thrown.

SEVERE:   Error Rendering View[/admin_side/Feedback.xhtml]
javax.ejb.EJBException
    at com.sun.ejb.containers.EJBContainerTransactionManager.processSystemException(EJBContainerTransactionManager.java:748)
    at com.sun.ejb.containers.EJBContainerTransactionManager.completeNewTx(EJBContainerTransactionManager.java:698)
    at com.sun.ejb.containers.EJBContainerTransactionManager.postInvokeTx(EJBContainerTransactionManager.java:503)
    at com.sun.ejb.containers.BaseContainer.postInvokeTx(BaseContainer.java:4475)
    at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:2009)
    at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:1979)
    at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:220)
    at com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate.invoke(EJBLocalObjectInvocationHandlerDelegate.java:88)
    at $Proxy662.getList(Unknown Source)
    at admin.bean.FeedbackManagedBean.load(FeedbackManagedBean.java:174)
    at org.primefaces.component.datatable.DataTable.loadLazyData(DataTable.java:815)
    at org.primefaces.component.datatable.DataTableRenderer.preRender(DataTableRenderer.java:93)
    at org.primefaces.component.datatable.DataTableRenderer.encodeEnd(DataTableRenderer.java:81)
    at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:919)
    at org.primefaces.renderkit.CoreRenderer.renderChild(CoreRenderer.java:85)
    at org.primefaces.renderkit.CoreRenderer.renderChildren(CoreRenderer.java:68)
    at org.primefaces.component.panel.PanelRenderer.encodeContent(PanelRenderer.java:204)
    at org.primefaces.component.panel.PanelRenderer.encodeMarkup(PanelRenderer.java:121)
    at org.primefaces.component.panel.PanelRenderer.encodeEnd(PanelRenderer.java:58)
    at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:919)
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1864)
    at javax.faces.render.Renderer.encodeChildren(Renderer.java:176)
    at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:889)
    at org.primefaces.renderkit.CoreRenderer.renderChild(CoreRenderer.java:81)
    at org.primefaces.renderkit.CoreRenderer.renderChildren(CoreRenderer.java:68)
    at org.primefaces.component.layout.LayoutUnitRenderer.encodeEnd(LayoutUnitRenderer.java:49)
    at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:919)
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1864)
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1860)
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1860)
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1860)
    at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:461)
    at com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:133)
    at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:337)
    at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:337)
    at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:120)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
    at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:219)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:647)
    at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1682)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:344)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
    at org.primefaces.webapp.filter.FileUploadFilter.doFilter(FileUploadFilter.java:70)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
    at filter.NoCacheFilter.doFilter(NoCacheFilter.java:28)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:316)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:160)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:734)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:673)
    at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:174)
    at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:357)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:260)
    at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:188)
    at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:191)
    at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:168)
    at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:189)
    at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:288)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:206)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:136)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:114)
    at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
    at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:838)
    at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:113)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:115)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:55)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:135)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:564)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:544)
    at java.lang.Thread.run(Thread.java:722)
Caused by: java.lang.IllegalArgumentException: An exception occured looking on class: class util.FeedbackUtils for constructor using selection criteria types as arguments.  If this CriteriaQuery was not intended to be a constructor query please verify that the selection matches the return type.
    at org.eclipse.persistence.internal.jpa.querydef.CriteriaQueryImpl.populateAndSetConstructorSelection(CriteriaQueryImpl.java:409)
    at org.eclipse.persistence.internal.jpa.querydef.CriteriaQueryImpl.select(CriteriaQueryImpl.java:93)
    at admin.beans.FeedbackBean.getList(FeedbackBean.java:145)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.glassfish.ejb.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:1081)
    at org.glassfish.ejb.security.application.EJBSecurityManager.invoke(EJBSecurityManager.java:1153)
    at com.sun.ejb.containers.BaseContainer.invokeBeanMethod(BaseContainer.java:4695)
    at com.sun.ejb.EjbInvocation.invokeBeanMethod(EjbInvocation.java:630)
    at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:822)
    at com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:582)
    at org.jboss.weld.ejb.AbstractEJBRequestScopeActivationInterceptor.aroundInvoke(AbstractEJBRequestScopeActivationInterceptor.java:46)
    at sun.reflect.GeneratedMethodAccessor478.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:883)
    at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:822)
    at com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:582)
    at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.doCall(SystemInterceptorProxy.java:163)
    at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.aroundInvoke(SystemInterceptorProxy.java:140)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:883)
    at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:822)
    at com.sun.ejb.containers.interceptors.InterceptorManager.intercept(InterceptorManager.java:369)
    at com.sun.ejb.containers.BaseContainer.__intercept(BaseContainer.java:4667)
    at com.sun.ejb.containers.BaseContainer.intercept(BaseContainer.java:4655)
    at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:212)
    ... 67 more
Caused by: java.lang.NoSuchMethodException: util.FeedbackUtils.<init>(java.lang.Long, java.lang.String, java.lang.String, org.joda.time.DateTime, java.lang.Boolean, java.lang.Long, java.lang.String)
    at java.lang.Class.getConstructor0(Class.java:2721)
    at java.lang.Class.getConstructor(Class.java:1674)
    at org.eclipse.persistence.internal.security.PrivilegedAccessHelper.getConstructorFor(PrivilegedAccessHelper.java:157)
    at org.eclipse.persistence.internal.jpa.querydef.CriteriaQueryImpl.populateAndSetConstructorSelection(CriteriaQueryImpl.java:396)
    ... 98 more

This works fine, when the type of testimonial is changed from Boolean to Object in the FeedbackUtils class.

Why it does not let a constructor query work, if it is given a Boolean type in the constructor list of parameters?

I'm using EclipseLink 2.5.1.


EDIT :

In the constructor of the FeedbackUtils class, the following check,

testimonial.getClass().getName()

returns java.lang.Boolean

and all of the following,

(testimonial instanceof Boolean)
testimonial.getClass().equals(Boolean.class)
testimonial.getClass().isAssignableFrom(Boolean.class)

return true.

Hence, the following type cast is also valid.

(Boolean)testimonial

Upto the associated XHTML page, it correctly behaves just like a Boolean.

Lachance answered 22/4, 2014 at 10:34 Comment(7)
File a bug to have the behavior changed, but the issue is that the TINYINT(1) type returned from the driver is passed to the constructor method as is. I'm guessing it returns a numeric type - check what the object type is in your constructor. When building a feedback instance, EclipseLink will convert from the driver returned type to the Boolean because it knows the type within the Feedback class, but it doesn't have the type information on the constructorOverline
It seems Boolean everywhere. Appended to the post.Lachance
The exception itself is clumsy : java.lang.NoSuchMethodException: util.FeedbackUtils.<init>(java.lang.Long, java.lang.String, java.lang.String, org.joda.time.DateTime, java.lang.Boolean, java.lang.Long, java.lang.String). It indicates the correct method signature including the parameter type java.lang.Boolean (not java.lang.Object) in its correct order. The method is already declared there in the FeedbackUtils class.Lachance
@Tiny: What MySQL version are you using ?Restless
@Restless : The MySQL version I'm using is 5.6.11. It should be more related to the ORM rather than the underlying database though.Lachance
I am just wondering if replacing the current column definition with @Column(name = "testimonial", columnDefinition = "BIT(1)") would help.Restless
@user75ponic : Exception stack-trace in quote is pretty much unreadable. Reverting the change.Lachance

© 2022 - 2024 — McMap. All rights reserved.