Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error after B06 : Internal Exception: java.lang.IndexOutOfBoundsException #2362

Open
anija-anil opened this issue Feb 7, 2025 · 10 comments
Open
Assignees

Comments

@anija-anil
Copy link
Contributor

Getting IndexOutOfBoundsException after upgrading to EclipseLink 5.0.0-B06

JPQL

UPDATE House o SET o.garage=?2, o.area=o.area+?3, o.kitchen.length=o.kitchen.length+?4, o.numBedrooms=?5 WHERE (o.parcelId=?1)

Exception

Exception [EclipseLink-6168] (Eclipse Persistence Services - 5.0.0-B06.v202502011023-b917c302c409eeca1a2c4002bd8b725a004ea7f6): org.eclipse.persistence.exceptions.QueryException
Exception Description: Query failed to prepare, unexpected error occurred: [java.lang.IndexOutOfBoundsException: Index 3 out of bounds for length 3].
Internal Exception: java.lang.IndexOutOfBoundsException: Index 3 out of bounds for length 3
Query: UpdateAllQuery(referenceClass=House jpql="UPDATE House o SET o.garage=?2, o.area=o.area+?3, o.kitchen.length=o.kitchen.length+?4, o.numBedrooms=?5 WHERE (o.parcelId=?1)")
	at org.eclipse.persistence.exceptions.QueryException.prepareFailed(QueryException.java:1604)
	at org.eclipse.persistence.queries.DatabaseQuery.checkPrepare(DatabaseQuery.java:715)
	at org.eclipse.persistence.queries.DatabaseQuery.checkPrepare(DatabaseQuery.java:645)
	at org.eclipse.persistence.internal.jpa.EJBQueryImpl.buildEJBQLDatabaseQuery(EJBQueryImpl.java:196)
	at org.eclipse.persistence.internal.jpa.EJBQueryImpl.buildEJBQLDatabaseQuery(EJBQueryImpl.java:120)
	at org.eclipse.persistence.internal.jpa.EJBQueryImpl.<init>(EJBQueryImpl.java:107)
	at org.eclipse.persistence.internal.jpa.EJBQueryImpl.<init>(EJBQueryImpl.java:91)
	at org.eclipse.persistence.internal.jpa.EntityManagerImpl.createQuery(EntityManagerImpl.java:1846)
@rfelcman
Copy link
Contributor

rfelcman commented Feb 7, 2025

Sorry provided info is not enough. Please add there at least entities which participates in query and query call with parameters.

@anija-anil
Copy link
Contributor Author

anija-anil commented Feb 10, 2025

Entity

<entity class="test.jakarta.data.web.House">
  <table name="House"/>
  <attributes>
   <basic name="area">
    <column nullable="false"/>
   </basic>
   <embedded name="garage">
    <attribute-override name="area">
     <column name="GARAGE_AREA"/>
    </attribute-override>
    <attribute-override name="type">
     <column name="GARAGE_TYPE"/>
    </attribute-override>
    <attribute-override name="door.height">
     <column name="GARAGE_DOOR_HEIGHT"/>
    </attribute-override>
    <attribute-override name="door.width">
     <column name="GARAGE_DOOR_WIDTH"/>
    </attribute-override>
   </embedded>
   <embedded name="kitchen">
    <attribute-override name="length">
     <column name="KITCHEN_LENGTH"/>
    </attribute-override>
    <attribute-override name="width">
     <column name="KITCHEN_WIDTH"/>
    </attribute-override>
   </embedded>
   <basic name="lotSize">
    <column nullable="false"/>
   </basic>
   <basic name="numBedrooms">
    <column nullable="false"/>
   </basic>
   <id name="parcelId">
   </id>
   <basic name="purchasePrice">
    <column nullable="false"/>
   </basic>
   <basic name="sold">
   </basic>
  </attributes>
 </entity>

@rfelcman Please find the entity we used .

@rfelcman
Copy link
Contributor

Sorry, but I need Java sources too like test.jakarta.data.web.House and related classes which are part of Entity tree.

@anija-anil
Copy link
Contributor Author

anija-anil commented Feb 10, 2025

public class House {
    public int area;

    public Garage garage;

    public Kitchen kitchen;

    public float lotSize;

    public int numBedrooms;

    public String parcelId;

    public float purchasePrice;

    public Year sold;
}

public class Garage {
    public static enum Type {
        Attached, Detached, TuckUnder
    };

    public int area;

    public GarageDoor door;

    public Type type;
}

public class Kitchen {

    public int length;

    public int width;
}

@rfelcman This entity lacks annotations because the entity itself is defined in orm.xml mentioned above.

@Tomas-Kraus Tomas-Kraus self-assigned this Feb 11, 2025
@Tomas-Kraus
Copy link
Member

This reproduction scenario is terrible, but I'll do my best to make it work. Please provide some small working project next time to avoid delays in bug fixes.

@Tomas-Kraus
Copy link
Member

Tomas-Kraus commented Feb 11, 2025

Anyway, the model seems to be wrong. I made a small application myself using the ORM provided here and I'm getting the following exception:

[ERROR] Errors: 
[ERROR]   TestBug.testUpdate:71 » IllegalArgument An exception occurred while creating a query in EntityManager: 
Exception Description: Problem compiling [UPDATE House h SET h.garage=?2, h.area=h.area+?3, h.kitchen.length=h.kitchen.length+?4, h.numBedrooms=?5 WHERE (h.parcelId=?1)]. 
[56, 72] An association field cannot be used in an update item's path expression. (UPDATE House h SET h.garage = ?2, h.area = h.area + ?3,  [ h.kitchen.length ] ...

Tried simplified query:

     UPDATE House h
        SET h.garage=?2, h.area=h.area+?3, h.numBedrooms=?4
      WHERE (h.parcelId=?1)

and it passes without any problem with latest EclipseLink master branch build.

My test application is here: https://github.com/Tomas-Kraus/eclipselink-bug/tree/bug-2362-simple - you need to checkout bug-2362-simple branch after clone.
Feel free to modify it to get the same exception as in this bug.
You need EclipseLink (https://github.com/eclipse-ee4j/eclipselink) master branch build locally because of 5.0.0-SNAPSHOT dependency in the POM.

@anija-anil
Copy link
Contributor Author

@Tomas-Kraus Thanks for sharing this. We will check and confirm.

@rfelcman
Copy link
Contributor

@anija-anil Sorry, but provided code is not enough. I'm missing complete ORM.xml file instead of provided fragment see e.g. https://github.com/eclipse-ee4j/eclipselink/blob/master/jpa/eclipselink.jpa.testapps/jpa.test.advanced2/src/main/resources/META-INF/advanced-orm.xml . From provided fragments is not clear entity ID where is stored JPQL .....
In case of classes. What about GarageDoor and Year which are not provided there.
DB model (DDL) is also needed.
Persistence unit definition from persistence.xml too.
I tried similar query test based on classes from #1850 and this one passed

    @Test
    public void testJPQLUpdateWithEmbeddablesWithValue03() {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory(PU_NAME);
        EntityManager em = emf.createEntityManager();
        EntityTransaction tx = em.getTransaction();

        try {
            Garage garage = new Garage(100, "Detached");
            tx.begin();
            Query query = em.createQuery("UPDATE House o SET o.garage.area=o.garage.area+?2, o.garage.type=?3 WHERE (o.parcelId=?1)");
            query.setParameter(1, "TestEmbeddable-304-3655-30");
            query.setParameter(2, garage.area);
            query.setParameter(3, garage.type);
            query.executeUpdate();
            tx.commit();
            House house = em.find(House.class, "TestEmbeddable-304-3655-30");
            assertNotNull(house);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException();
        }
        finally {
            if (em.getTransaction().isActive()) {
                em.getTransaction().rollback();
            }
            em.close();
            emf.close();
        }
    }

@ChithraMini
Copy link

Adding the entity classes used for recreating the issue:

------------House-------------------

@entity
public class House {

@Id
private String parcelId;

@Basic(optional = false)
private double area;

@Embedded
private Garage garage; // Embedded garage object

@Embedded
private Kitchen kitchen; // Embedded kitchen object

@Basic(optional = false)
private double lotSize;

@Basic(optional = false)
private int numBedrooms;

@Basic(optional = false)
private double purchasePrice;

private boolean sold;

// Getters and Setters
public String getParcelId() {
    return parcelId;
}

public void setParcelId(String parcelId) {
    this.parcelId = parcelId;
}

public double getArea() {
    return area;
}

public void setArea(double area) {
    this.area = area;
}

public Garage getGarage() {
    return garage;
}

public void setGarage(Garage garage) {
    this.garage = garage;
}

public Kitchen getKitchen() {
    return kitchen;
}

public void setKitchen(Kitchen kitchen) {
    this.kitchen = kitchen;
}

public double getLotSize() {
    return lotSize;
}

public void setLotSize(double lotSize) {
    this.lotSize = lotSize;
}

public int getNumBedrooms() {
    return numBedrooms;
}

public void setNumBedrooms(int numBedrooms) {
    this.numBedrooms = numBedrooms;
}

public double getPurchasePrice() {
    return purchasePrice;
}

public void setPurchasePrice(double purchasePrice) {
    this.purchasePrice = purchasePrice;
}

public boolean isSold() {
    return sold;
}

public void setSold(boolean sold) {
    this.sold = sold;
}

@Override
public String toString() {
    return "House [parcelId=" + parcelId + ", area=" + area + ", garage=" + garage + ", kitchen=" + kitchen + ", lotSize=" + lotSize + ", numBedrooms=" + numBedrooms
           + ", purchasePrice=" + purchasePrice + ", sold=" + sold + "]";
}

}

----------------Kitchen-----------------
@embeddable
public class Kitchen {

private double length;
private double width;

// Getters and Setters
public double getLength() {
    return length;
}

public void setLength(double length) {
    this.length = length;
}

public double getWidth() {
    return width;
}

public void setWidth(double width) {
    this.width = width;
}

}
------------Garage----------------

@embeddable
public class Garage {

public static enum Type {
    Attached, Detached, TuckUnder
};

@Column(name = "GARAGE_AREA")
private double area;

@Column(name = "GARAGE_TYPE")
private Type type;

//@Embedded
//@OneToOne
private Door door;

// Getters and Setters
public double getArea() {
    return area;
}

public void setArea(double area) {
    this.area = area;
}

public Type getType() {
    return type;
}

public void setType(Type type) {
    this.type = type;
}

public Door getDoor() {
    return door;
}

public void setDoor(Door door) {
    this.door = door;
}

}
-------------------------Door----------------
//@embeddable
public class Door implements Serializable {

private static final long serialVersionUID = 1L; // Optional: for version control of the serialized object.

@Column(name = "GARAGE_DOOR_HEIGHT")
private double height;

@Column(name = "GARAGE_DOOR_WIDTH")
private double width;

// Getters and Setters
public double getHeight() {
    return height;
}

public void setHeight(double height) {
    this.height = height;
}

public double getWidth() {
    return width;
}

public void setWidth(double width) {
    this.width = width;
}

}

@ChithraMini
Copy link

---------DDL----------------
CREATE TABLE HOUSE (PARCELID VARCHAR(255) NOT NULL, AREA FLOAT, LOTSIZE FLOAT, NUMBEDROOMS INTEGER, PURCHASEPRICE FLOAT, SOLD SMALLINT DEFAULT 0, GARAGE_AREA FLOAT, GARAGE_TYPE INTEGER, GARAGE_DOOR_HEIGHT FLOAT, GARAGE_DOOR_WIDTH FLOAT, LENGTH FLOAT, WIDTH FLOAT, PRIMARY KEY (PARCELID))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants