eclipse-ee4j / eclipse-ee4j/eclipselink

EclipseLink assumes that Query.setParameter(Parameter<T> param, T value)'s param object is an EclipseLink type

Open
#1,990 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Java
Stars
246
Forks
202
Avg merge
1d 22h
Merged PRs (30d)
14

Description

Spring Data JPA creates a JPA-compliant `Parameter` instance and supplies it through `Query.setParameter(Parameter param, T value)`. This ends up inside `EJBQueryImpl`, where it breaks.

```java
@Override
public TypedQuery setParameter(Parameter param, T value) {
if (param == null) {
throw new IllegalArgumentException(ExceptionLocalization.buildMessage("NULL_PARAMETER_PASSED_TO_SET_PARAMETER"));
}
//bug 402686: type validation
String position = getParameterId(param); // <----- this is where it fails
ParameterExpressionImpl parameter = (ParameterExpressionImpl) this.getInternalParameters().get(position);
if (parameter == null ) {
throw new IllegalArgumentException(ExceptionLocalization.buildMessage("NO_PARAMETER_WITH_NAME", new Object[] { param.toString(), this.databaseQuery }));
}
if (!parameter.getParameterType().equals(param.getParameterType())) {
throw new IllegalArgumentException(ExceptionLocalization.buildMessage("INCORRECT_PARAMETER_TYPE", new Object[] { position, param.getParameterType() }));
}
return this.setParameter(position, value);
}
```

When it invokes `getParameterId` against the `Parameter`, EL is assuming that this is an internal type instead of a JPA type, and attempts a cast operation, which in our situation fails.

```java
public static String getParameterId(Parameter param){
Integer id= param.getPosition();
if (id == null ){
return String.valueOf(((ParameterExpressionImpl)param).getInternalName()); // <--- perhaps param.getName() instead?
}
return String.valueOf(id);
}
```

Because we are supplying a name-based parameter, a JPA `Parameter.getName()` operation, which would have worked, is traded for a downcast and then an invocation for an internal name operation.

Perhaps consider FIRST checking if there is a `param.getName()` result and deferring to that?

You're clearly using the `getPosition()` call, so why not stick to the interface operations?

Contributor guide

Open the contributing guide

Research direction

Start in EJBQueryImpl at setParameter(Parameter, T) and trace getParameterId, especially the cast used for name-based parameters. Check the JPA Parameter interface operations and existing query tests; done means a standard named Parameter is accepted without an EclipseLink-specific cast while positional parameters and type validation continue to work.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
database
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.