access keycloak principal in #query Jparepository - spring

i'm using keycloak along with spring boot, and i'm trying to access the principal object on a custom query in my JPA repository
my query :
#Query(value = "SELECT CAST (CASE WHEN COUNT(p) > 0 THEN 1 ELSE 0 END AS BIT) FROM product WHERE p.created_by = ?#{authentication.name} AND p.name = ?#{name}",nativeQuery = true)
public abstract boolean existsByNameForCurrentUser(String name);
i've added this bean on my configuration:
#Bean
public SecurityEvaluationContextExtension securityEvaluationContextExtension() {
return new SecurityEvaluationContextExtension();
}
the error i'm getting is :
org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'authentication' cannot be found on object of type 'java.lang.Object[]' - maybe not public or not valid?
the principal object is accessible anywhere on my project, so i don't know why i'm getting this error.
Thanks in advance.

Related

Custom queries on mongodb reactive repository spring boot

Following this example I am trying to create custom queries, using the reactive mongo template.
I have defined the following files
Repository definition
#Repository
public interface SimulationRepository extends ReactiveMongoRepository<Simulation, String>, PersSimRepo {
#Query("{userId : ?0}")
public Flux<Simulation> findByUserId(String userId);
#Query("{userId : ?0}")
public Flux<Simulation> findByUserId(String userId, Pageable pageable);
public Mono<Long> countByUserId(String userId);
}
Custom query interface
public interface PersSimRepo {
Flux<Simulation> aaa(String userId, Sort sort, List<GlobalSimStatus> status);
}
Custom query implementation
#Slf4j
public class PerSimRepoImpl implements PersSimRepo {
private final ReactiveMongoTemplate mongoTemplate;
public PerSimRepoImpl(ReactiveMongoTemplate mongoTemplate) {
this.mongoTemplate = mongoTemplate;
}
#Override
public Flux<Simulation> aaa(String userId, Sort sort, List<GlobalSimStatus> status) {
log.info("status:{}", status);
Query query = new Query();
query.addCriteria(Criteria.where("userId").is(userId).and("status").in(status));
return mongoTemplate.find(query.with(sort), Simulation.class);
}
}
When I try to start the project I get this exception
Could not create query for public abstract reactor.core.publisher.Flux it.reply.evtb.repository.specialization.PersSimRepo.aaa(java.lang.String,org.springframework.data.domain.Sort,java.util.List); Reason: No property 'aaa' found for type 'Simulation'; nested exception is org.springframework.data.mapping.PropertyReferenceException: No property 'aaa' found for type 'Simulation'
Where Simulation is the object, apparently spring looks for a "aaa" field inside Simulation
This looks like a bug to me, I can't figure out where I am wrong, I use spring boot 2.7.5

Using projection with a interface in `#Query` annotation with a native query gives "Target type is not an interface and no matching Converter found"

I have a table with a clob in an oracle 19 database which I try to fetch with a native query using a #Query annotation with a projection from a Spring boot 2.7.4 application. I get the following error message:
java.lang.UnsupportedOperationException: Cannot project jdk.proxy2.$Proxy281 implementing java.sql.Clob,org.hibernate.engine.jdbc.WrappedClob,java.io.Serializable to java.lang.String; Target type is not an interface and no matching Converter found
The query from my repository class:
#Query(
value = """
select submission_id as "submissionId", text as "textAnswer"
from answer
where answer_id = :answerId
""",
nativeQuery = true)
public MyDTO findDTO(Long answerId);
My interface which I use for the projection:
public interface MyDTO {
String getTextAnswer();
}
From my domain object annotated with #Entity:
private String textAnswer;
My testcase which reproduce which reproduce this error. If I comment out the line with a.getTextAnswer() it runs ok.
#Test
public void findFormPublishedAnswersInterfaceDTOById() {
FormPublishedAnswersInterfaceDTO a = answerRepository.findFormPublishedAnswersInterfaceDTOById(21540241L);
assertEquals("test", a.getTextAnswer());
}
I have tried different hints I found by the help of google :) like annotating private String textAnswer with #Lob, #Type(type = "text") and #Column(name = "text", columnDefinition = "CLOB") without any luck.
If you read the exception carefully, you should understand that the JDBC driver reports that the type is a Clob, so your DTO must look like this instead:
public interface MyDTO {
Clob getTextAnswer();
}

Jackson java.util.Optional serialization does not include type ID

I got the following classes:
#JsonIdentityInfo(
generator = ObjectIdGenerators.IntSequenceGenerator.class,
property = "oid"
)
#JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "clazz")
#JsonSubTypes({
#JsonSubTypes.Type(value = MySubEntity.class, name = "MySubEntity"),
})
public abstract class Entity {
...
}
public class MySubEntity extends Entity {
...
}
Now when I serialize that MySubEntity wrapped in an Optional then JSON does not contain the clazz attribute containing the type ID. Bug? When I serialize to List<MySubEntity> or just to MySubEntity it works fine.
Setup: jackson-databind 2.9.4, jackson-datatype-jdk8 2.9.4, serialization is done in Spring Boot application providing a RESTful web service.
EDIT: Here is the Spring REST method that returns the Optional:
#RequestMapping(method = RequestMethod.GET, value = "/{uuid}", produces = "application/json")
public Optional<MySubEntity> findByUuid(#PathVariable("uuid") String uuid) {
...
}
EDIT:
I made a SSCCE with a simple Spring REST controller and two tests. The first test is using ObjectMapper directly which is successful in deserialization although the clazz is missing. The second test calls the REST controller and fails with an error because clazz is missing:
Error while extracting response for type [class com.example.demo.MySubEntity] and content type [application/json;charset=UTF-8]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Missing type id when trying to resolve subtype of [simple type, class com.example.demo.MySubEntity]: missing type id property 'clazz'; nested exception is com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Missing type id when trying to resolve subtype of [simple type, class com.example.demo.MySubEntity]: missing type id property 'clazz'
This, indeed, looks like a bug. There is one workaround that I can suggest for this case, is to use JsonTypeInfo.As.EXISTING_PROPERTY and add field clazz to your Entity. There only one case with this approach is that the clazz must be set in java code manually. However this is easy to overcome.
Here is the full code for suggested workaround:
#JsonIdentityInfo(
generator = ObjectIdGenerators.IntSequenceGenerator.class,
property = "oid"
)
#JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.EXISTING_PROPERTY, //field must be present in the POJO
property = "clazz")
#JsonSubTypes({
#JsonSubTypes.Type(value = MySubEntity.class, name = "MySubEntity"),
})
public abstract class Entity {
#JsonProperty
private String uuid;
//Here we have to initialize this field manually.
//Here is the simple workaround to initialize in automatically
#JsonProperty
private String clazz = this.getClass().getSimpleName();
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public String getClazz() {
return clazz;
}
public void setClazz(String clazz) {
this.clazz = clazz;
}
}

Spring Rest Hibernate Update List with PUT method

I'm tying to update List with a rest service, but an InvalidDataAccessApiUsageException is thrown :
Parameter value element [Sharing{uuid=af777b47-3dfc...updated=2016-05-04T10:37:29.000Z}] did not match expected type [java.util.UUID (n/a)]
Controller :
#RequestMapping(value = "/updateChecked", method = RequestMethod.PUT, consumes = MediaType.APPLICATION_JSON_VALUE)
public int update(#RequestBody SharingList shares){
return this.sharingService.updateChecked(shares);
}
Service :
public int updateChecked(SharingList shares) {
int updated = sharingDao.setCheckedSharingFor(shares);
return updated;
}
DAO :
#Modifying
#Query("UPDATE Sharing s SET s.checked=1 WHERE uuid in :shares")
int setCheckedSharingFor(#Param("shares") SharingList shares);
SharingList:
public class SharingList extends ArrayList<Sharing> {
}
What is wrong please ?
There is the answer here
Sharing{uuid=af777b47-3dfc...updated=2016-05-04T10:37:29.000Z}]
did not match expected type [java.util.UUID (n/a)]
Hibernate doesn't have artificial intelligence to understand that it should get uuid from Sharing.
Fo this query
#Query("UPDATE Sharing s SET s.checked=1 WHERE uuid in :shares")
you should provide a collection of UUID as the shares parameter.

Spring Data MongoDB #Indexed annotation - create index error (system.indexes) during find query operation

I am facing a weird issue as this has been working earlier with no issues.
I am using latest Spring Data MongoDB 1.5.2 release with Mongo Java Driver 2.12.3
I have used mongoDB ensureIndex command to create index on a collection field manaully through Mongo Shell (MongoDB serevr running with MongoDB 2.4 version).
I have checked both on my collection with collection.getIndexes() command and system.indexes collection too that the above index is created correctly.
With Spring Data MongoDB, I have also placed #Indexed annotation on same field in domain object.
During a query find operation, I was getting below Spring Data MongoDB create index exception for creating index in system.indexes collection and complained the document obj size is greater then 16MB.
If, I remove #Indexed annotation on domain object field and re-run the find query, then there are no errors from application side.
I would like to understand as why:
1) Spring Data MongoDB is trying to create index in system.indexes during a find query operation with #Indexed annotation available.
2) Why Spring Data MongoDB complains obj size is greater then 16 MB during find query operation with #Indexed annotation, whereas I can run the same find query on MongoDB shell with no issues.
3) Is the above document in collection is corrupt? Do I have to re-import fresh data again and test the same as this has been working in the past with no issues from application side?
4) What is the life cycle of Spring Data MongoDB #Indexed annotation or How does it works? Do we have any documentation available in details?
Domain Object
#Document(collection = "Users")
public class Users implements Serializable {
#Id
ObjectId id;
#Indexed
String appUserId
String firstName;
String lastName;
}
#Repository
public interface UsersRepository extends MongoRepository<Users, String>, UsersRepositoryCustom {
// default query methods
}
#Repository
public interface UsersRepositoryCustom {
int findUserCount(String appUserId);
}
#Component
public class UsersRepositoryImpl implements UsersRepositoryCustom {
#Override
public int findUserCount(String appUserId) {
DBCursor dbCursor = null;
int count = 0;
Query query = new Query();
query.addCriteria(
Criteria.where("appUserId").is(appUserId));
try {
DBCollection dbCollection = mongoOperations.getCollection("Users");
System.out.println("Start time : " + new Date().toString());
dbCursor = dbCollection.find(query.getQueryObject());
//while (dbCursor.hasNext()) {
//do dome processing
}
count = dbCursor.count();
System.out.println("End time : " + new Date().toString());
} finally {
dbCursor.close();
}
return count;
}
}
Caused by: com.mongodb.WriteConcernException: { "serverUsed" : "XXXXXXXX:11111" , "err" : "BSONObj size: 0 (0x00000000) is invalid. Size must be between 0 and 16793600(16MB) First element: EOO" , "code" : 10334 , "n" : 0 , "connectionId" : 341 , "ok" : 1.0}
at com.mongodb.CommandResult.getWriteException(CommandResult.java:90)
at com.mongodb.CommandResult.getException(CommandResult.java:79)
at com.mongodb.CommandResult.throwOnError(CommandResult.java:131)
at com.mongodb.DBTCPConnector._checkWriteError(DBTCPConnector.java:135)
at com.mongodb.DBTCPConnector.access$000(DBTCPConnector.java:39)
at com.mongodb.DBTCPConnector$1.execute(DBTCPConnector.java:186)
at com.mongodb.DBTCPConnector$1.execute(DBTCPConnector.java:181)
at com.mongodb.DBTCPConnector.doOperation(DBTCPConnector.java:210)
at com.mongodb.DBTCPConnector.say(DBTCPConnector.java:181)
at com.mongodb.DBCollectionImpl.insertWithWriteProtocol(DBCollectionImpl.java:530)
at com.mongodb.DBCollectionImpl.createIndex(DBCollectionImpl.java:369)
at com.mongodb.DBCollection.createIndex(DBCollection.java:564)
at org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexCreator.createIndex(MongoPersistentEntityIndexCreator.java:135)
at org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexCreator.checkForAndCreateIndexes(MongoPersistentEntityIndexCreator.java:129)
at org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexCreator.checkForIndexes(MongoPersistentEntityIndexCreator.java:121)
at org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexCreator.onApplicationEvent(MongoPersistentEntityIndexCreator.java:105)
at org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexCreator.onApplicationEvent(MongoPersistentEntityIndexCreator.java:46)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:98)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:333)
at org.springframework.data.mapping.context.AbstractMappingContext.addPersistentEntity(AbstractMappingContext.java:307)
at org.springframework.data.mapping.context.AbstractMappingContext.getPersistentEntity(AbstractMappingContext.java:181)
at org.springframework.data.mapping.context.AbstractMappingContext.getPersistentEntity(AbstractMappingContext.java:141)
at org.springframework.data.mapping.context.AbstractMappingContext.getPersistentEntity(AbstractMappingContext.java:67)
at org.springframework.data.mongodb.repository.support.MongoRepositoryFactory.getEntityInformation(MongoRepositoryFactory.java:141)
at org.springframework.data.mongodb.repository.support.MongoRepositoryFactory.getTargetRepository(MongoRepositoryFactory.java:83)
at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:158)
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.initAndReturn(RepositoryFactoryBeanSupport.java:224)
at org.springframework.data.repository.core.support.`enter code here`RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:210)
at org.springframework.data.mongodb.repository.support.MongoRepositoryFactoryBean.afterPropertiesSet(MongoRepositoryFactoryBean.java:108)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1612)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1549)

Resources