Issue
I need to access current locale in Spring Repository using SpEL.
I have next Repository
:
@Repository
public interface RoomRepository extends JpaRepository<Room, Long> {
@Query(..."left join rc.roomClassTranslations rct on rct.language = ?#{SpEL expression})
List<RoomDTO> findAllRooms(Sort sort);
}
I tried several expressions but none of them worked.
#{@localeResolver.resolveLocale(#httpServletRequest).toLanguageTag()} "...)
In this expression httpServletRequest is null, if I change it to @httpServletRequest
, it will give an error that no bean is found. I also tried to rewrite it like this
#{LocaleContextHolder.getLocale().toLanguageTag()}
this will give next error:
EL1011E: Method call: Attempted to call method getLocale() on null context object.
So how to access current locale in SpEL expression?
Solution
Spring support the usage of restricted SpEL template expressions in manually defined queries that are defined with @Query
.
Spring Data exposes an extension point EvaluationContextExtension
.
Spring Data JPA will pick up all beans of type EvaluationContextExtension
and use those to prepare the EvaluationContext
to be used to evaluate the SpEL expression defined in @Query
.
Let's implement the locale extension as an example.
@Component
public class LocaleEvaluationContextExtension
implements EvaluationContextExtension {
@Override
public Map<String, Object> getProperties() {
Map<String, Object> properties = new HashMap<>(
EvaluationContextExtension.super.getProperties());
return properties;
}
@Override
public String getExtensionId() {
return "locale";
}
@Override
public Object getRootObject() {
return LocaleContextHolder.getLocale();
}
}
The query method definition should be:
@Query(..."left join rc.roomClassTranslations rct on " +
"rct.language = ?#{locale.language})
List<RoomDTO> findAllRooms(Sort sort);
Answered By - İsmail Y.
Answer Checked By - Senaida (JavaFixing Volunteer)