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

Projection Not working for Array Of Object [DATACMNS-1656] #2079

Closed
spring-projects-issues opened this issue Jan 17, 2020 · 7 comments
Closed
Assignees
Labels
in: repository Repositories abstraction status: invalid An issue that we don't feel is valid type: bug A general bug

Comments

@spring-projects-issues
Copy link

spring-projects-issues commented Jan 17, 2020

vr025 opened DATACMNS-1656 and commented

We are using Projection to select just single Column that is String Array (String[]) and it is falling with Index out of bound exception.

 

 

Here is my table:

     create table IF NOT EXISTS ORGANIZATION (
          uuid uuid not NULL PRIMARY KEY,
          name varchar(127) not NULL,
           appliance_tags varchar(255)[]
            constraint name_key unique (name)
       );

 

Here is my original entity mapping:

@Entity
@TypeDefs(

{               @TypeDef( name = "string-array", typeClass = StringArrayType.class ),                      @TypeDef( name = "pgsql_enum", typeClass = PostgreSQLEnumType.class)                     }

)
@Table(name = "organization")
@XmlRootElement(name = "organization")
@JsonInclude(Include.NON_EMPTY)
public class Organization

@Column(name = "name")
private String name;

 

@Id
@Column(name = "uuid")
private UUID uuid;


@Type( type = "string-array" )
@Column(name = "appliance_tags")
private String [] applianceTags;

 

//getters and setters for the above fields

  

 

 

Here is Projection Interface:

@Projection(name="appliacneTags", types = \{Organization.class})
public interface OrgTag

{ public String[] getApplianceTags(); }

 

Repository Query:

@Query(value = "select org.applianceTags from Organization as org")
public List<OrgTag> findAllTags();

 

 

Error Logs :

java.lang.IndexOutOfBoundsException: Index 1 out of bounds for length 1
at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:248)
at java.base/java.util.Objects.checkIndex(Objects.java:372)
at java.base/java.util.ArrayList.get(ArrayList.java:458)
at org.springframework.data.repository.query.ResultProcessor$ProjectingConverter.toMap(ResultProcessor.java:310)
at org.springframework.data.repository.query.ResultProcessor$ProjectingConverter.getProjectionTarget(ResultProcessor.java:298)
at org.springframework.data.repository.query.ResultProcessor$ProjectingConverter.convert(ResultProcessor.java:285)
at org.springframework.data.repository.query.ResultProcessor$ChainingConverter$1.convert(ResultProcessor.java:210)
at org.springframework.data.repository.query.ResultProcessor$ChainingConverter.convert(ResultProcessor.java:221)
at org.springframework.data.repository.query.ResultProcessor.processResult(ResultProcessor.java:152)
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:133)
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:118)

Affects: 2.2.4 (Moore SR4)

Reference URL: https://github.com/spring-projects/spring-data-commons/blob/master/src/main/java/org/springframework/data/repository/query/ResultProcessor.java

@spring-projects-issues
Copy link
Author

Mark Paluch commented

If you would like us to spend some time helping you to diagnose the problem, please spend some time describing it and, ideally, providing a minimal sample that reproduces the problem

@spring-projects-issues
Copy link
Author

vr025 commented

I think toMap() method needs to check boundary condition and if it is array or list set value. 

 

private Object getProjectionTarget(Object source) { private Object getProjectionTarget(Object source) {

if (source != null && source.getClass().isArray()) { source = Arrays.asList((Object[]) source); }
     if (source instanceof Collection) { return toMap((Collection<?>) source,          type.getInputProperties()); }
       return source;

 

}
private static Map<String, Object> toMap(Collection<?> values, List<String> names) {
int i = 0; Map<String, Object> result = new HashMap<>(values.size());
for (Object element : values) { result.put(names.get(i++), element); }
return result; }

@spring-projects-issues
Copy link
Author

Oliver Drotbohm commented

It looks like we're not properly handling the returned array and invalidly try to create a single projecting instance of OrgTag around the returned array.

That said, your projection declaration is invalid: the query returns an array of String. The result is declared as a List<OrgTag>. I.e. even if our code was working correctly you'd get us trying to project OrgTag onto a single String which would produce a proper instance but you're never gonna see getApplianceTags() working as that method does not exist on String.

You should be able to see this working by changing the type of applianceTags to List<String> instead of String[].

That said, please make sure you properly format code in the examples you provide using the \{{code}} tags

@spring-projects-issues
Copy link
Author

vr025 commented

I have a PostgreSQL table which I mentioned in the description. That table has a colunmn with String Array type. When I try to access that column values through projection, the ResultProcessor.java file is throwing "index out of bound exception", I pasted the errors for your reference.

 

There is no Boundary conditions checked for list or set from a column.

 

 

 

@spring-projects-issues
Copy link
Author

Oliver Drotbohm commented

Did you read my response to what you provided?

Also, please refrain from messing with the ticket details. We use those for internal organization. Thanks

@spring-projects-issues
Copy link
Author

vr025 commented

After changing the repository method to List<String[]> I'm able to get the tags array for all the names in the organization table. Thanks Oliver for your inputs. However please let me know how to use projections for String Array.

 

Now I completely removed projection interface and changed my repository query like below to get all the list of tags for each name.

 

Modified Repository Query is here :

@Query(value = "select org.applianceTags from Organization as org")

public List<String[]> findAllTags();

@spring-projects-issues spring-projects-issues added status: waiting-for-feedback We need additional information before we can continue type: bug A general bug in: repository Repositories abstraction labels Dec 30, 2020
@mp911de mp911de added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Dec 30, 2020
@mp911de
Copy link
Member

mp911de commented Jan 18, 2021

Projections are intended to retain their multiplicity. That being said, a String[] must remain a collection type of String and cannot be projected into a singular type.

@mp911de mp911de closed this as not planned Won't fix, can't repro, duplicate, stale Sep 13, 2023
@mp911de mp911de added status: invalid An issue that we don't feel is valid and removed status: feedback-provided Feedback has been provided labels Sep 13, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: repository Repositories abstraction status: invalid An issue that we don't feel is valid type: bug A general bug
Projects
None yet
Development

No branches or pull requests

3 participants