Bug #88543 NullPointerException from QueryDomainType
Submitted: 17 Nov 2017 21:28 Modified: 13 Dec 2017 21:41
Reporter: Michael Seydel Email Updates:
Status: Can't repeat Impact on me:
None 
Category:MySQL Cluster: Cluster/J Severity:S2 (Serious)
Version:7.5.7 OS:Linux
Assigned to: MySQL Verification Team CPU Architecture:Any
Tags: npe, NullPointerException, QueryDomainType

[17 Nov 2017 21:28] Michael Seydel
Description:
Occasionally we see in production a NullPointerException when calling getResultList() on a Query object. Here is the relevant part of a stack trace:

 com.mysql.clusterj.ClusterJException: Exception executing query. Caused by java.lang.NullPointerException:null
     at com.mysql.clusterj.core.query.QueryDomainTypeImpl.getResultData(QueryDomainTypeImpl.java:336)
     at com.mysql.clusterj.core.query.QueryDomainTypeImpl.getResultList(QueryDomainTypeImpl.java:181)
     at com.mysql.clusterj.core.query.QueryImpl.getResultList(QueryImpl.java:146)

We have not discovered any way to reproduce the issue, and it happens infrequently. What follows is some example code that has reproduce it in production for us:

            final QueryBuilder builder = clusterJSession.getQueryBuilder();
            final QueryDomainType<IUserTile> domain = builder.createQueryDefinition(IUserTile.class);
            domain.where(domain.get("userUUID").equal(domain.param("user_uuid")).
                    and(domain.get("modeCode").in(domain.param("modes"))));

            final List<Integer> modeColumns = new ArrayList<>(2);
            modeColumns.add(0);
            modeColumns.add(4);

            final Query<IUserTile> query = clusterJSession.createQuery(domain);
            query.setParameter("user_uuid", userUUID);
            query.setParameter("modes", modeColumns);
            return query.getResultList();

With the following for the interface(s):

@PersistenceCapable(table = "user_tile")
@Index(name = "idx_uhash")
public interface IUserTile extends ITileEntity {

    @PrimaryKey(columns = {@Column(name = "user_uuid"), @Column(name = "tile_uuid"), @Column(name = "mode")})

    @Column(name = "user_uuid")
    @Index(name = "idx_user")
    public String getUserUUID();

    public void setUserUUID(String userUUID);

    @Column(name = "tile_uuid")
    @Index(name = "idx_tile")
    public String getTileUUID();

    public void setTileUUID(String tileUUID);

    @Column(name = "other_user_uuid")
    public String getOtherUserUUID();

    public void setOtherUserUUID(String userUUID);

    @Column(name = "mode")
    public int getModeCode();

    public void setModeCode(int modeCode);
}

public interface ITileEntity {
    @Column(name = "creation_origin", allowsNull = "NO")
    @JsonIgnore
    public byte getCreationOrigin();

    public void setCreationOrigin(byte origin);

    @Column(name = "creation_timestamp", allowsNull = "NO")
    @JsonIgnore
    public long getCreationTimestamp();

    public void setCreationTimestamp(long creationTimestamp);

    @Column(name = "last_modified_timestamp", allowsNull = "NO")
    @JsonIgnore
    public long getLastModifiedTimestamp();

    public void setLastModifiedTimestamp(long timestamp);
}

and schema definition:

CREATE TABLE IF NOT EXISTS user_tile (
    user_uuid VARCHAR(64) NOT NULL,
    tile_uuid VARCHAR(64) NOT NULL,
    mode int  NOT NULL,
    creation_origin TINYINT NOT NULL,
    creation_timestamp BIGINT NOT NULL,
    other_user_uuid VARCHAR(64) CHARACTER SET latin1 NOT NULL,
    last_modified_timestamp BIGINT NOT NULL,

    PRIMARY KEY (`user_uuid`,`tile_uuid`,`other_user_uuid`),
    INDEX idx_user(user_uuid),
    INDEX idx_tile(tile_uuid)
) engine=ndb
;

How to repeat:
Not repeatable.

Suggested fix:
None; if ClusterJ source code is available, pointing us toward that might help us investigate the issue.
[13 Dec 2017 16:51] John Duncan
In a MySQL Cluster source distribution, ClusterJ source can be found under storage/ndb/clusterj
Then the file you want here is under clusterj-core/src/main/ ... /query/
[13 Dec 2017 18:55] MySQL Verification Team
Hi,

The clusterJ is opensource, and my colleague pointed you to the source location already. As for the issue reported I cannot reproduce it.

all best
Bogdan
[13 Dec 2017 19:56] Michael Seydel
> In a MySQL Cluster source distribution, ClusterJ source can be found under storage/ndb/clusterj

Where is the "source distribution"? I have looked and never found it.

I downloaded a dmg file from https://dev.mysql.com/downloads/cluster/ which contained a pkg file which installed to the local directory /usr/local/mysql-cluster-gpl-7.5.5-macos10.12-x86_64/
That folder does not contain a "storage" folder. Can you please tell me what I'm doing wrong?
[13 Dec 2017 20:48] MySQL Verification Team
Hi,
you go to place where you download gpl files for cluster:

https://dev.mysql.com/downloads/cluster/

You select operating system "source code" not macos/osx :D and then fetch "Generic Linux (Architecture Independent), Compressed TAR Archive"

https://dev.mysql.com/get/Downloads/MySQL-Cluster-7.5/mysql-cluster-gpl-7.5.8.tar.gz

and inside
mysql-cluster-gpl-7.5.8.tar.gz\mysql-cluster-gpl-7.5.8\storage\ndb\clusterj\clusterj-core\src\main\java\com\mysql\clusterj\core\query\*.java :D

all best
Bogdan
[13 Dec 2017 21:41] Michael Seydel
Thank you very much, I didn't think to look for a source distribution under "operating system." I realize this bug is not reproducible, but hopefully having the source code to ClusterJ now will help with our analysis.