eclipse-ee4j / eclipse-ee4j/eclipselink
EclipseLink assumes that Query.setParameter(Parameter<T> param, T value)'s param object is an EclipseLink type
- 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
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