<mailto:
tom.ware@xxxxxxxxxx>> wrote:
        Laird,
         Can you also provide information about how your persistence
        unit and Entity caching is setup.  What persistence unit
        properties are you using related to caching?  Do you have
        caching options in orm.xml files?  Are there caching annotations
        besides the ones in the source provided below?
        -Tom
        Christopher Delahunt wrote:
            Hi Laird,
            Can you catch the exception and try calling
            JPAHelper.getEntityManager(em).getServerSession().getIdentityMapAccessor().printIdentityMap(AnswerEntity.class)
            ?
            This will show what is in the shared cache for this class
            when the exception occurs.  Also, can you turn logging on to
            finest?  This will show the exact revision of EclipseLink
            being used (I'm not sure which was
            picked up by Glassfish 3.1b36), and the log might help track
            down how a null is getting into the cache though hopefully
            it is not needed.
            I believe it might be being nulled out due to garbage
            collection.  If that is the case, a workaround might be to
            increase the size of the cache used for that object
            (assuming you are using a softCacheWeakIdentityMap), switch
            to a fullidentitymap, or set it to
            be isolated.
            Best Regards,
            Chris
            On 10/01/2011 10:31 AM, Laird Nelson wrote:
                (Oh, /not/ a simple bug; my mistake in my earlier
                response.  Sorry; long day already and it's just begun.)
                I've included a snippet of the code that builds and runs
                the query.
                This use case is actually not necessarily all that
                strange.  Imagine if you will a survey application where
                multiple choice answers are stored in tables, each of
                which has a structure like all the others.  Let's say
                there's a table named HomelessShelters, and it has rows
                that name homeless shelters in the greater metro area.
                 Each row has an ID ("7") and a text ("Pine Street Inn").
                 From these identically structured tables we can build
                up a set of Answer entities.  An Answer entity is mapped
                like this:
                @Entity(name = "Answer")
                @IdClass(AnswerEntity.AnswerID.class)
                @Table(name = "Answer")
                public class AnswerEntity implements Answer {
                 /**
                  * The {@link NamedAnswerSet} to which this {@link
                AnswerEntity}
                  * belongs.  This field may be {@code null} only at
                construction
                  * time.
                  */
                 @JoinColumn(insertable = false, name = "ANSWERSETNAME",
                nullable = false, updatable = false) // name must be
                uppercase for portability
                 @ManyToOne(fetch = FetchType.EAGER, optional = false,
                targetEntity = NamedAnswerSetEntity.class)
                 @NotNull
                 NamedAnswerSet answerSet;
                  /**
                  * The opaque and unique identifier for this {@link
                AnswerEntity}.
                  */
                 @Column(name = "ID") // name must be uppercase for
                portability
                 @Id
                 private int id;
                 @Column(name = "ANSWERSETNAME") // name must be
                uppercase for portability
                 @Id
                 @NotNull
                 private String answerSetName;
                 /**
                  * The text describing this {@link AnswerEntity}.  This
                field may be
                  * {@code null} only at construction time.
                  */
                 @Basic(optional = false)
                 @Column(length = 100, name = "TEXT", nullable = false)
                // name must be uppercase for portability
                 @NotNull
                 private String text;
                 /**
                  * A comma and/or whitespace-delimited {@link String}
                of identifiers
                  * usually supplied by the {@link TableAnswerSetEntity}
                that built
                  * this {@link AnswerEntity}.  An {@link AnswerEntity} will
                  * typically sift through this {@link String} to see if
                its {@link
                  * #getID() ID} is contained in it.
                  *
                  * @see #isFreeResponsePermitted()
                  */
                 @Column(name = "FREERESPONSEIDS", length = 255,
                updatable = false)
                 private String freeResponseIds;
                 /**
                  * A {@link Boolean} representing the result of combing
                through the
                  * {@link #freeResponseIds} field for our own {@link
                #getID() id}.
                  *
                  * @see #isFreeResponsePermitted()
                  */
                 @Transient
                 private Boolean freeResponsePermitted;
                }
                Logically all AnswerEntities belong to AnswerSets.  One
                kind of AnswerSet is one drawn from a table in the
                manner that I've described.  Others include constrained
                numeric AnswerSets; still others are defined more or
                less out of thin air and backed by Drools, the JBoss
                rules engine.  Short answer: build an AnswerEntity one
                way or another, and that's what you pick when you choose
                an answer to a multiple choice question.
                So this query is concerned with constructing
                AnswerEntities out of particular kinds of tables.
                Here is a snippet of code that builds and runs the
                query.  I have not yet sanitized the inputs; obviously I
                need to guard against SQL injection here in a way that
                normally, using garden variety PreparedStatements, I
                wouldn't.
                final String tableName = "HomelessShelters"; // real
                code obviously gets this from somewhere else
                final String answerSetName = this.getName(); // e.g.
                "HomelessSheltersAnswerSet"
                assert answerSetName != null;
                final String sql;
                final StringBuilder sb = new StringBuilder("SELECT t.%s
                AS ID, '%s' AS ANSWERSETNAME, t.%s AS TEXT, %s AS
                FREERESPONSEIDS FROM %s t");
                if (orderByColumnName != null) {
                 sb.append(" ORDER BY %s");
                 sql = String.format(sb.toString(),
                this.getIDColumnName(), answerSetName,
                this.getTextColumnName(), this.freeResponseIds == null ?
                "NULL" : String.format("\"%s\"", this.freeResponseIds),
                tableName, orderByColumnName);
                } else {
                 sql = String.format(sb.toString(),
                this.getIDColumnName(), answerSetName,
                this.getTextColumnName(), this.freeResponseIds == null ?
                "NULL" : String.format("\"%s\"", this.freeResponseIds),
                tableName);
                }
                *final Query q = em.createNativeQuery(sql,
                AnswerEntity.class);*
                assert q != null;
                @SuppressWarnings("unchecked")
                final List<AnswerEntity> results = q.getResultList();
                assert results != null;
                for (final AnswerEntity a : results) {
                 if (a != null) {
                   a.setAnswerSet(this);
                 }
                }
                returnValue = new LinkedHashSet<AnswerEntity>(results);
                So nothing too odd going on here, I don't think, at
                least where the query is concerned.
                Best,
                Laird
                On Mon, Jan 10, 2011 at 9:53 AM, Tom Ware
                <
tom.ware@xxxxxxxxxx <mailto:
tom.ware@xxxxxxxxxx>