HibernateEntityValueEncoder NullPointerException
Asked Answered
E

2

0

I'm using a CRUD framework called Tynamo, which in turn relies on Apache Tapestry and Hibernate. This all works fine, except for when I try to use it for CRUD on a table with a composite/compound primary key.

I've decided not to go the @EmbeddedId route, since it seems to not work at all with the framework. That being said, I have been using the @IdClass method, which is mostly working; I think I'm a line or two of code away from success.

The issue is that when it starts using reflection to build the objects, it blows up and says, org.apache.tapestry5.ioc.internal.util.TapestryException, caused by java.lang.NullPointerException at org.apache.tapestry5.internal.hibernate.HibernateEntityValueEncoder.<init>(HibernateEntityValueEncoder.java:51).

I honestly have no idea what's the deal here, but since I have normal table CRUD operation working for numerous other tables, I would assume this is somehow related to this table using a composite/compound primary key.

One thing I did try was to move the static inner class to its own package and remove the static class modifier, but the exact same error occurred.

You can see my class below:

package com.company.crud.entities;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.IdClass;

import com.company.crud.entities.TransferExtension.TransferExtensionPK;

@Entity(name = "Transfer_Extensions")
@IdClass(TransferExtensionPK.class)
public class TransferExtension implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    // @NotNull(message = "Please supply a Script Code")
    // @Length(min = 3, max = 4)
    @Column(name = "Division", nullable = false)
    private String scriptCode;

    @Id
    // @NotNull(message = "Please supply a Transfer Type")
    // @Length(min = 3, max = 6)
    @Column(name = "Transfer_Type", nullable = false)
    private String transferType;

    @Column(name = "Extension", nullable = true)
    private String englishExtension;

    @Column(name = "Span_Extension", nullable = true)
    private String spanishExtension;

    @Column(name = "Call_Type", nullable = true)
    private String callType;

    @Column(name = "Call_Center", nullable = true)
    private String callCenter;

    public TransferExtension() {
    }

    public TransferExtension(String scriptCode, String transferType,
            String englishExtension, String spanishExtension, String callType,
            String callCenter) {

        this.callCenter = callCenter;
        this.callType = callType;
        this.englishExtension = englishExtension;
        this.scriptCode = scriptCode;
        this.spanishExtension = spanishExtension;
        this.transferType = transferType;
    }

    public String getScriptCode() {
        return this.scriptCode;
    }

    public void setScriptCode(String scriptCode) {
        this.scriptCode = scriptCode;
    }

    public String getTransferType() {
        return this.transferType;
    }

    public void setTransferType(String transferType) {
        this.transferType = transferType;
    }

    public String getEnglishExtension() {
        return this.englishExtension;
    }

    public void setEnglishExtension(String englishExtension) {
        this.englishExtension = englishExtension;
    }

    public String getSpanishExtension() {
        return this.spanishExtension;
    }

    public void setSpanishExtension(String spanishExtension) {
        this.spanishExtension = spanishExtension;
    }

    public String getCallType() {
        return this.callType;
    }

    public void setCallType(String callType) {
        this.callType = callType;
    }

    public String getCallCenter() {
        return this.callCenter;
    }

    public void setCallCenter(String callCenter) {
        this.callCenter = callCenter;
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append("TransferExtension [scriptCode=")
                .append(this.scriptCode).append(", transferType=")
                .append(this.transferType).append(", englishExtension=")
                .append(this.englishExtension).append(", spanishExtension=")
                .append(this.spanishExtension).append(", callType=")
                .append(this.callType).append(", callCenter=")
                .append(this.callCenter).append("]");
        return builder.toString();
    }

    public static class TransferExtensionPK implements Serializable {
        private static final long serialVersionUID = 4L;

        private String scriptCode;
        private String transferType;

        public TransferExtensionPK() {
        }

        public TransferExtensionPK(String scriptCode, String transferType) {

            this.scriptCode = scriptCode;
            this.transferType = transferType;
        }

        public String getScriptCode() {
            return this.scriptCode;
        }

        public void setScriptCode(String scriptCode) {
            this.scriptCode = scriptCode;
        }

        public String getTransferType() {
            return this.transferType;
        }

        public void setTransferType(String transferType) {
            this.transferType = transferType;
        }

        @Override
        public String toString() {
            StringBuilder builder = new StringBuilder();
            builder.append("TransferExtensionPK [scriptCode=")
                    .append(this.scriptCode).append(", transferType=")
                    .append(this.transferType).append("]");
            return builder.toString();
        }

        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime
                    * result
                    + ((this.scriptCode == null) ? 0 : this.scriptCode
                            .hashCode());
            result = prime
                    * result
                    + ((this.transferType == null) ? 0 : this.transferType
                            .hashCode());
            return result;
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (obj == null) {
                return false;
            }
            if (!(obj instanceof TransferExtensionPK)) {
                return false;
            }
            TransferExtensionPK other = (TransferExtensionPK) obj;
            if (this.scriptCode == null) {
                if (other.scriptCode != null) {
                    return false;
                }
            } else if (!this.scriptCode.equals(other.scriptCode)) {
                return false;
            }
            if (this.transferType == null) {
                if (other.transferType != null) {
                    return false;
                }
            } else if (!this.transferType.equals(other.transferType)) {
                return false;
            }
            return true;
        }
    }
}

And the stack trace:

Hibernate: 
    select
        count(*) as y0_ 
    from
        Transfer_Extensions this_
Hibernate: 
    select
        top 25 this_.Division as Division1_0_,
        this_.Transfer_Type as Transfer2_1_0_,
        this_.Call_Center as Call3_1_0_,
        this_.Call_Type as Call4_1_0_,
        this_.Extension as Extension1_0_,
        this_.Span_Extension as Span6_1_0_ 
    from
        Transfer_Extensions this_
[ERROR] pages.List Render queue error in BeginRender[List:pagelink_0]: org.apache.tapestry5.ioc.internal.util.TapestryException
org.apache.tapestry5.ioc.internal.util.TapestryException [at context:List.tml, line 16]
    at org.apache.tapestry5.internal.structure.ComponentPageElementImpl$AbstractPhase.invoke(ComponentPageElementImpl.java:158)
    at org.apache.tapestry5.internal.structure.ComponentPageElementImpl$BeginRenderPhase.render(ComponentPageElementImpl.java:214)
    at org.apache.tapestry5.internal.services.RenderQueueImpl.run(RenderQueueImpl.java:72)
    at org.apache.tapestry5.internal.services.PageRenderQueueImpl.render(PageRenderQueueImpl.java:124)
    at $PageRenderQueue_11b9cd02019b.render(Unknown Source)
    at $PageRenderQueue_11b9cd02019a.render(Unknown Source)
    at org.apache.tapestry5.internal.services.MarkupRendererTerminator.renderMarkup(MarkupRendererTerminator.java:37)
    at org.apache.tapestry5.services.TapestryModule$31.renderMarkup(TapestryModule.java:1994)
    at $MarkupRenderer_11b9cd02019e.renderMarkup(Unknown Source)
    at org.apache.tapestry5.services.TapestryModule$30.renderMarkup(TapestryModule.java:1978)
    at $MarkupRenderer_11b9cd02019e.renderMarkup(Unknown Source)
    at org.apache.tapestry5.services.TapestryModule$29.renderMarkup(TapestryModule.java:1960)
    at $MarkupRenderer_11b9cd02019e.renderMarkup(Unknown Source)
    at org.apache.tapestry5.services.TapestryModule$28.renderMarkup(TapestryModule.java:1945)
    at $MarkupRenderer_11b9cd02019e.renderMarkup(Unknown Source)
    at org.apache.tapestry5.services.TapestryModule$27.renderMarkup(TapestryModule.java:1931)
    at $MarkupRenderer_11b9cd02019e.renderMarkup(Unknown Source)
    at org.apache.tapestry5.services.TapestryModule$26.renderMarkup(TapestryModule.java:1913)
    at $MarkupRenderer_11b9cd02019e.renderMarkup(Unknown Source)
    at org.apache.tapestry5.services.TapestryModule$25.renderMarkup(TapestryModule.java:1894)
    at $MarkupRenderer_11b9cd02019e.renderMarkup(Unknown Source)
    at $MarkupRenderer_11b9cd020199.renderMarkup(Unknown Source)
    at org.apache.tapestry5.internal.services.PageMarkupRendererImpl.renderPageMarkup(PageMarkupRendererImpl.java:47)
    at $PageMarkupRenderer_11b9cd020192.renderPageMarkup(Unknown Source)
    at org.apache.tapestry5.internal.services.PageResponseRendererImpl.renderPageResponse(PageResponseRendererImpl.java:67)
    at $PageResponseRenderer_11b9cd020194.advised$renderPageResponse_11b9cd020196(Unknown Source)
    at $PageResponseRenderer_11b9cd020194$Invocation_renderPageResponse_11b9cd020195.proceedToAdvisedMethod(Unknown Source)
    at org.apache.tapestry5.internal.plastic.AbstractMethodInvocation.proceed(AbstractMethodInvocation.java:84)
    at org.tynamo.services.TynamoCoreModule$2.advise(TynamoCoreModule.java:353)
    at org.apache.tapestry5.internal.plastic.AbstractMethodInvocation.proceed(AbstractMethodInvocation.java:86)
    at $PageResponseRenderer_11b9cd020194.renderPageResponse(Unknown Source)
    at $PageResponseRenderer_11b9cd020189.renderPageResponse(Unknown Source)
    at org.apache.tapestry5.internal.services.PageRenderRequestHandlerImpl.handle(PageRenderRequestHandlerImpl.java:64)
    at org.apache.tapestry5.services.TapestryModule$38.handle(TapestryModule.java:2222)
    at $PageRenderRequestHandler_11b9cd02018b.handle(Unknown Source)
    at $PageRenderRequestHandler_11b9cd020186.handle(Unknown Source)
    at org.apache.tapestry5.internal.services.ComponentRequestHandlerTerminator.handlePageRender(ComponentRequestHandlerTerminator.java:48)
    at org.apache.tapestry5.services.InitializeActivePageName.handlePageRender(InitializeActivePageName.java:47)
    at $ComponentRequestHandler_11b9cd020187.handlePageRender(Unknown Source)
    at $ComponentRequestHandler_11b9cd020080.handlePageRender(Unknown Source)
    at org.tynamo.routing.services.RouterDispatcher.dispatch(RouterDispatcher.java:26)
    at $Dispatcher_11b9cd020084.dispatch(Unknown Source)
    at $Dispatcher_11b9cd02007d.dispatch(Unknown Source)
    at org.apache.tapestry5.services.TapestryModule$RequestHandlerTerminator.service(TapestryModule.java:302)
    at org.apache.tapestry5.internal.services.RequestErrorFilter.service(RequestErrorFilter.java:26)
    at $RequestHandler_11b9cd02007e.service(Unknown Source)
    at org.apache.tapestry5.services.TapestryModule$3.service(TapestryModule.java:902)
    at $RequestHandler_11b9cd02007e.service(Unknown Source)
    at org.apache.tapestry5.services.TapestryModule$2.service(TapestryModule.java:892)
    at $RequestHandler_11b9cd02007e.service(Unknown Source)
    at org.apache.tapestry5.internal.services.StaticFilesFilter.service(StaticFilesFilter.java:90)
    at $RequestHandler_11b9cd02007e.service(Unknown Source)
    at org.apache.tapestry5.internal.services.CheckForUpdatesFilter$2.invoke(CheckForUpdatesFilter.java:105)
    at org.apache.tapestry5.internal.services.CheckForUpdatesFilter$2.invoke(CheckForUpdatesFilter.java:95)
    at org.apache.tapestry5.ioc.internal.util.ConcurrentBarrier.withRead(ConcurrentBarrier.java:85)
    at org.apache.tapestry5.internal.services.CheckForUpdatesFilter.service(CheckForUpdatesFilter.java:119)
    at $RequestHandler_11b9cd02007e.service(Unknown Source)
    at $RequestHandler_11b9cd020072.service(Unknown Source)
    at org.apache.tapestry5.services.TapestryModule$HttpServletRequestHandlerTerminator.service(TapestryModule.java:253)
    at org.apache.tapestry5.internal.gzip.GZipFilter.service(GZipFilter.java:53)
    at $HttpServletRequestHandler_11b9cd020074.service(Unknown Source)
    at org.apache.tapestry5.upload.internal.services.MultipartServletRequestFilter.service(MultipartServletRequestFilter.java:44)
    at $HttpServletRequestHandler_11b9cd020074.service(Unknown Source)
    at org.apache.tapestry5.internal.services.IgnoredPathsFilter.service(IgnoredPathsFilter.java:62)
    at $HttpServletRequestFilter_11b9cd020070.service(Unknown Source)
    at $HttpServletRequestHandler_11b9cd020074.service(Unknown Source)
    at org.apache.tapestry5.services.TapestryModule$1.service(TapestryModule.java:852)
    at $HttpServletRequestHandler_11b9cd020074.service(Unknown Source)
    at $HttpServletRequestHandler_11b9cd02006e.service(Unknown Source)
    at org.apache.tapestry5.TapestryFilter.doFilter(TapestryFilter.java:171)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1476)
    at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:501)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:137)
    at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:557)
    at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:231)
    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1086)
    at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:429)
    at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:193)
    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1020)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:135)
    at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:255)
    at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:154)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:116)
    at org.eclipse.jetty.server.Server.handle(Server.java:370)
    at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:494)
    at org.eclipse.jetty.server.AbstractHttpConnection.headerComplete(AbstractHttpConnection.java:971)
    at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.headerComplete(AbstractHttpConnection.java:1033)
    at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:644)
    at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:235)
    at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:82)
    at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:696)
    at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:53)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:608)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:543)
    at java.lang.Thread.run(Thread.java:744)
Caused by: java.lang.NullPointerException
    at org.apache.tapestry5.internal.hibernate.HibernateEntityValueEncoder.<init>(HibernateEntityValueEncoder.java:51)
    at org.apache.tapestry5.hibernate.HibernateModule$1.create(HibernateModule.java:103)
    at org.apache.tapestry5.internal.services.ValueEncoderSourceImpl.getValueEncoder(ValueEncoderSourceImpl.java:48)
    at $ValueEncoderSource_11b9cd0200bf.getValueEncoder(Unknown Source)
    at org.apache.tapestry5.internal.services.ContextValueEncoderImpl.toClient(ContextValueEncoderImpl.java:35)
    at $ContextValueEncoder_11b9cd0200cd.toClient(Unknown Source)
    at org.apache.tapestry5.internal.services.ContextPathEncoderImpl.encodeValue(ContextPathEncoderImpl.java:48)
    at org.apache.tapestry5.internal.services.ContextPathEncoderImpl.encodeIntoPath(ContextPathEncoderImpl.java:72)
    at $ContextPathEncoder_11b9cd02008f.encodeIntoPath(Unknown Source)
    at org.apache.tapestry5.internal.services.ComponentEventLinkEncoderImpl.appendContext(ComponentEventLinkEncoderImpl.java:516)
    at org.apache.tapestry5.internal.services.ComponentEventLinkEncoderImpl.createPageRenderLink(ComponentEventLinkEncoderImpl.java:103)
    at org.apache.tapestry5.internal.services.linktransform.LinkTransformerInterceptor.createPageRenderLink(LinkTransformerInterceptor.java:50)
    at $ComponentEventLinkEncoder_11b9cd020082.createPageRenderLink(Unknown Source)
    at org.apache.tapestry5.internal.services.LinkSourceImpl.createPageRenderLink(LinkSourceImpl.java:119)
    at $LinkSource_11b9cd0200ce.createPageRenderLink(Unknown Source)
    at org.apache.tapestry5.internal.structure.ComponentPageElementResourcesImpl.createPageRenderLink(ComponentPageElementResourcesImpl.java:111)
    at org.apache.tapestry5.internal.structure.ComponentPageElementImpl.createPageLink(ComponentPageElementImpl.java:1271)
    at org.apache.tapestry5.internal.structure.InternalComponentResourcesImpl.createPageLink(InternalComponentResourcesImpl.java:221)
    at org.apache.tapestry5.corelib.components.PageLink.beginRender(PageLink.java:57)
    at org.apache.tapestry5.corelib.components.PageLink.beginRender(PageLink.java)
    at org.apache.tapestry5.internal.structure.ComponentPageElementImpl$BeginRenderPhase.invokeComponent(ComponentPageElementImpl.java:207)
    at org.apache.tapestry5.internal.structure.ComponentPageElementImpl$AbstractPhase.invoke(ComponentPageElementImpl.java:138)
    ... 94 more

Here's my ValueEncoder class:

import org.apache.tapestry5.ValueEncoder;
import org.apache.tapestry5.services.ValueEncoderFactory;

import com.company.ivr.crud.entities.TransferExtension.TransferExtensionPK;

public class TransferExtensionPKValueEncoder implements
        ValueEncoderFactory<TransferExtensionPK>,
        ValueEncoder<TransferExtensionPK> {

    public ValueEncoder<TransferExtensionPK> create(
            Class<TransferExtensionPK> type) {

        return this;
    }

    public String toClient(TransferExtensionPK value) {

        return value.getScriptCode() + ":" + value.getTransferType();
    }

    public TransferExtensionPK toValue(String clientValue) {

        String[] values = clientValue.split(":");
        return new TransferExtensionPK(values[0], values[1]);
    }
}

Here's the AppModule class:

package com.company.crud.services;

import org.apache.tapestry5.SymbolConstants;
import org.apache.tapestry5.ValueEncoder;
import org.apache.tapestry5.hibernate.HibernateEntityPackageManager;
import org.apache.tapestry5.ioc.Configuration;
import org.apache.tapestry5.ioc.MappedConfiguration;
import org.apache.tapestry5.ioc.ServiceBinder;
import org.apache.tapestry5.ioc.annotations.Contribute;
import org.apache.tapestry5.ioc.services.ApplicationDefaults;
import org.apache.tapestry5.ioc.services.FactoryDefaults;
import org.apache.tapestry5.ioc.services.SymbolProvider;
import org.apache.tapestry5.services.BeanBlockContribution;
import org.apache.tapestry5.services.BeanBlockSource;
import org.apache.tapestry5.services.DisplayBlockContribution;
import org.apache.tapestry5.services.ValueEncoderFactory;
import org.apache.tapestry5.upload.services.UploadSymbols;
import org.tynamo.builder.Builder;
import org.tynamo.builder.BuilderDirector;

import com.company.crud.encoders.TransferExtensionPKValueEncoder;
import com.company.crud.entities.TransferExtension.TransferExtensionPK;

public class AppModule {

    /* 
    *   This is the method I've added.
    */
    // @Contribute(ValueEncoderSource.class)
    public static void contributeValueEncoderSource(
            MappedConfiguration<Class<?>, ValueEncoderFactory<?>> config) {

        config.addInstance(TransferExtensionPK.class,
                TransferExtensionPKValueEncoder.class);
    }

    public static void bind(ServiceBinder binder) {
    }

    @Contribute(SymbolProvider.class)
    @ApplicationDefaults
    public static void provideSymbols(
            MappedConfiguration<String, String> configuration) {
        configuration.add(SymbolConstants.SUPPORTED_LOCALES, "en, es");
        configuration.add(UploadSymbols.REQUESTSIZE_MAX, "2048000");
        configuration.add(UploadSymbols.FILESIZE_MAX, "2048000");
    }

    @Contribute(SymbolProvider.class)
    @FactoryDefaults
    public static void overrideFactorySymbols(
            MappedConfiguration<String, Object> configuration) {
        configuration.override(SymbolConstants.APPLICATION_VERSION,
                "0.0.1-SNAPSHOT");
    }

    @Contribute(BeanBlockSource.class)
    public static void addCustomBlocks(
            Configuration<BeanBlockContribution> configuration) {
        configuration.add(new DisplayBlockContribution("boolean",
                "blocks/DisplayBlocks", "check"));
        configuration.add(new DisplayBlockContribution(
                "single-valued-association", "blocks/DisplayBlocks",
                "showPageLink"));
        configuration.add(new DisplayBlockContribution(
                "many-valued-association", "blocks/DisplayBlocks",
                "showPageLinks"));
    }

    @Contribute(HibernateEntityPackageManager.class)
    public static void addPackagesToScan(Configuration<String> configuration) {
    }

    @Contribute(BuilderDirector.class)
    public static void addBuilders(
            MappedConfiguration<Class<?>, Builder<?>> configuration) {
    }
}
Efrainefram answered 20/1, 2015 at 19:25 Comment(0)
P
1

Tapestry will need a ValueEncoder for all primary key types so that it can convert from clientside string to servierside object. There are built in ValueEncoders for String and Long etc so this is usually not an issue. I'm guessing you'll need to contribute a ValueEncoderFactory to the ValueEncoderSource for TransferExtensionPK.

eg:

public class TransferExtensionPKValueEncoder implements ValueEncoderFactory<TransferExtensionPK>, ValueEncoder<TransferExtensionPK> {
    public ValueEncoder<TransferExtensionPK> create(Class<TransferExtensionPK> type) {
       return this;
    }
    public String toClient(TransferExtensionPK value) {
       return value.getScriptCode() + ":" + getTransferType();
    }
    public TransferExtensionPK toValue(String clientValue) {
       String[] values = clientValue.split(":");
       return new TransferExtensionPK(values[0], values[1]);
    }
}

public class MyModule {
    public static void contributeValueEncoderSource(MappedConfiguration<Class, ValueEncoderFactory> config) {
        config.addInstance(TransferExtensionPK.class, TransferExtensionPKValueEncoder.class);
    }
}

Please report back if this fixes the problem as tapestry-hibernate should ideally give a nicer exception message.

Hibernate sucks for composite primary keys... I usually avoid them all together and all my tables have a sequence generated long as a primary key. It makes things much easier.

Penetration answered 21/1, 2015 at 15:55 Comment(11)
I'll try this out shortly and see if it helps. The advice makes sense, especially since you linked to the ValueEncoder doc, which I really appreciate. And yes, I've been through this rigmarole with composite keys and Hibernate before at an earlier job - if I have control over database design, I take the same approach as you for keys...but that's not the case this time, unfortunately :/Efrainefram
so, i've attempted what you suggested, but i'm not sure i've done it entirely correctly, specifically the contributeValueEncoder() method. i've updated my original post to include the updated code, etc. that you recommended i make. are you able to provide additional suggestions for me, please?Efrainefram
Use my code exactly. I didn't use @Contribute(ValueEncoder.class) and used the naming convention instead. If you want annotations, it should be @Contribute(ValueEncoderSource.class)Penetration
gotcha. i've tried both with and without the annotation (it "worked" when i changed to ValueEncoderSource), and i get the same error with the same line numbers as the original stack trace i posted. and the reason i used the annotation at all is because the archetype-generated AppModule class is using them, so i wanted to be consistent. also, thank you so much for your quick responses, that's very nice of you.Efrainefram
What's the value of tapestry.app-package in your app? Since your entity is in the package "com.company.crud.entities" tapestry.app-package should be "com.company.crud" correct?Penetration
yep, that's its value.Efrainefram
You have two @Id properties on your entity. Perhaps you should try a single TransferExtensionPK property to simplify things.Penetration
i'll give it a shot, but i can't mix and match like that. to use the TransferExtensionPK, I'd have to change my hibernate annotations to use @Embeddable and @EmbeddedId and then get rid of the class annotation, @IdClass. but i'll switch things up and see what happens.Efrainefram
Worth a try just to see what's going on... this is why I hate composite keys in hibernate... it's a real ball ache!Penetration
Let us continue this discussion in chat.Efrainefram
I think I'm blocked from chat by firewall. See my other answer... should fix your problemPenetration
P
1

Seems like built-in ValueEncoder is not quite up-to-task for this composite primary key entity. You can easily override the ValueEncoder for the whole entity

eg:

public class TransferExtensionValueEncoder implements ValueEncoderFactory<TransferExtension>, ValueEncoder<TransferExtension> {
    @Inject Session hibernateSession;

    public ValueEncoder<TransferExtension> create(Class<TransferExtension> type) {
       return this;
    }
    public String toClient(TransferExtension value) {
       return value.getScriptCode() + ":" + getTransferType();
    }
    public TransferExtension toValue(String clientValue) {
       String[] values = clientValue.split(":");
       Query query = hibernateSession
           .createQuery("from TransferExtension where scriptCode = :scriptCode and transferType = :transferType")
           .setParameter("scriptCode", values[0])
           .setParameter("transferType", values[1]);

       return (TransferExtension) query.uniqueResult();
    }
}

public class MyModule {
    public static void contributeValueEncoderSource(MappedConfiguration<Class, ValueEncoderFactory> config) {
        // use overrideInstance to override the default HibernateEntityValueEncoder just for this one entity
        config.overrideInstance(TransferExtension.class, TransferExtensionValueEncoder.class);
    }
}
Penetration answered 29/1, 2015 at 16:10 Comment(2)
i appreciate your help, but at this point, i'm going to push for adding an id column to the database and testing that change against existing functionality. this approach is becoming untenable, as i have to keep an eye to the future for maintenance, etc. i'm absolutely not trying to create a crud project where sql must be written, and i need to have others on my team be able to maintain and extend the initial functionality i'm building out right now. while this may eventually work with enough tinkering, it's become evident to me that what should be a very simple project is becoming complex.Efrainefram
that's what i'd do... push for a pk on every table. Trust me it'll make life a lot easier.Penetration

© 2022 - 2024 — McMap. All rights reserved.