Home > Mobile >  Spring Expression Language (SpEL) access locale in Repository Query
Spring Expression Language (SpEL) access locale in Repository Query

Time:03-30

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?

CodePudding user response:

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);
  • Related