Does it exist a way for autowiring any Spring #Component inside a JPA repository? - spring

The point is i have a Custom JPA Repository which is load using "#EnableJpaRepositories", but inside of this Custom JPA repository i do autowire another Spring Bean annotated with #Component, but it never comes filled, always bringing a null reference...
I read that JPA Repository does join and share the same Spring Application Context and so it cannot see those Beans loaded by the common Application Context... Is it really true? If so, is there any way to glue them and make Custom Repositories to inject my componentes properly???
Down here the relevant code:
public class DefaultCrudRepository<T extends IdentifiableEntity> extends QuerydslJpaRepository<T, BigInteger>
implements CrudRepository<T> {
private static final EntityPathResolver DEFAULT_ENTITY_PATH_RESOLVER = SimpleEntityPathResolver.INSTANCE;
private JpaEntityInformation<T, BigInteger> jpaEntityInformation;
private EntityManager entityManager;
private EntityPath<T> path;
private PathBuilder<T> builder;
private Querydsl querydsl;
#Autowired
private SortComponent sortComponent;
#Autowired
private PageComponent pageComponent;
#Autowired
private FilterComponent filterComponent;
#Autowired
private ExpandComponent expandComponent;
public DefaultCrudRepository(JpaEntityInformation<T, BigInteger> jpaEntityInformation, EntityManager entityManager,
EntityPathResolver resolver) {
super(jpaEntityInformation, entityManager, resolver);
this.jpaEntityInformation = jpaEntityInformation;
this.entityManager = entityManager;
this.path = resolver.createPath(jpaEntityInformation.getJavaType());
this.builder = new PathBuilder<T>(path.getType(), path.getMetadata());
this.querydsl = new Querydsl(entityManager, builder);
this.expandComponent = new DefaultExpandComponent(entityManager);
this.sortComponent = new DefaultSortComponent();
this.filterComponent = new DefaultFilterComponent();
this.pageComponent = new DefaultPageComponent();
init();
}
public DefaultCrudRepository(JpaEntityInformation<T, BigInteger> jpaEntityInformation,
EntityManager entityManager) {
this(jpaEntityInformation, entityManager, DEFAULT_ENTITY_PATH_RESOLVER);
this.jpaEntityInformation = jpaEntityInformation;
this.entityManager = entityManager;
}
/*
* private Class<?> getDomainClass(Class<?> clazz) { Type type =
* clazz.getGenericSuperclass(); if (type instanceof ParameterizedType) {
* ParameterizedType parameterizedType = (ParameterizedType) type; return
* (Class<?>) parameterizedType.getActualTypeArguments()[0]; } else { return
* getDomainClass(clazz.getSuperclass()); } }
*/
#PostConstruct
private void init() {
this.filterComponent.init(this.jpaEntityInformation.getJavaType());
this.expandComponent.init(this.jpaEntityInformation.getJavaType());
}
#Override
public <S extends T> List<S> save(Iterable<S> entities) {
List<S> savedEntities = super.save(entities);
super.flush();
this.entityManager.refresh(savedEntities);
return savedEntities;
}
#Override
public <S extends T> S save(S entity) {
S savedEntity = super.save(entity);
super.flush();
if (!this.jpaEntityInformation.isNew(entity)) {
this.entityManager.refresh(savedEntity);
}
return savedEntity;
}
protected JPQLQuery<T> createQuery(final Predicate predicate, final EntityGraph<?> entityGraph) {
JPQLQuery<?> query = createQuery(predicate);
if (entityGraph != null) {
((AbstractJPAQuery<?, ?>) query).setHint(EntityGraphType.LOAD.getKey(), entityGraph);
}
return query.select(path);
}
protected Page<T> findAll(final Pageable pageable, final Predicate predicate, final EntityGraph<?> entityGraph) {
final JPQLQuery<?> countQuery = createCountQuery(predicate);
JPQLQuery<T> query = querydsl.applyPagination(pageable, createQuery(predicate, entityGraph));
return PageableExecutionUtils.getPage(query.fetch(), pageable, new LongSupplier() {
#Override
public long getAsLong() {
return countQuery.fetchCount();
}
});
}
#Override
public Page<T> findAll(Integer pageNumber, Integer pageSize, BooleanExpression booleanExpression,
String filterExpression, String sortExpression, String expandExpression)
throws InvalidFilterExpressionException, InvalidSortExpressionException,
InvalidExpandExpressionException {
Sort sort = null;
if (sortExpression != null && !sortExpression.isEmpty()) {
sort = this.sortComponent.getSort(sortExpression);
}
Pageable pageable = this.pageComponent.getPage(pageNumber, pageSize, sort);
BooleanExpression filterBooleanExpression = null;
if (filterExpression != null) {
filterBooleanExpression = this.filterComponent.getBooleanExpression(filterExpression);
}
BooleanExpression mergedBooleanExpression = null;
if (booleanExpression != null && filterBooleanExpression != null) {
mergedBooleanExpression = booleanExpression.and(filterBooleanExpression);
} else if (booleanExpression != null && filterBooleanExpression == null) {
mergedBooleanExpression = booleanExpression;
} else if (booleanExpression == null && filterBooleanExpression != null) {
mergedBooleanExpression = filterBooleanExpression;
}
EntityGraph<?> entityGraph = null;
if (expandExpression != null && !expandExpression.isEmpty()) {
entityGraph = this.expandComponent.getEntityGraph(expandExpression);
}
return this.findAll(pageable, mergedBooleanExpression, entityGraph);
}
protected Predicate getPredicate(final BigInteger identifier, final Predicate predicate) {
Class<?> clazz = this.jpaEntityInformation.getJavaType();
String name = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, clazz.getSimpleName());
Path<?> rootPath = Expressions.path(this.jpaEntityInformation.getJavaType(), name);
Class<?> idType = this.jpaEntityInformation.getIdType();
String idAttributeName = this.jpaEntityInformation.getIdAttribute().getName();
Path<?> leftPath = Expressions.path(idType, rootPath, idAttributeName);
Expression<?> rightExpression = Expressions.constant(identifier);
BooleanExpression booleanExpression = Expressions.predicate(Ops.EQ, leftPath, rightExpression);
BooleanBuilder booleanBuilder = new BooleanBuilder(booleanExpression);
booleanBuilder.and(predicate);
return booleanBuilder.getValue();
}
protected T findOne(final BigInteger identifier, final BooleanExpression booleanExpression,
final EntityGraph<?> entityGraph) {
Assert.notNull(identifier, "The given id must not be null!");
T object = null;
if (booleanExpression != null) {
Predicate mergedPredicate = getPredicate(identifier, booleanExpression);
JPQLQuery<T> query = createQuery(mergedPredicate, entityGraph);
object = query.fetchOne();
} else {
Map<String, Object> hints = new HashMap<String, Object>();
if (entityGraph != null) {
hints.put("javax.persistence.loadgraph", entityGraph);
}
object = this.entityManager.find(this.jpaEntityInformation.getJavaType(), identifier, hints);
}
return object;
}
#Override
public T findOne(final BigInteger identifier, final BooleanExpression booleanExpression,
final String expandExpression) throws InvalidExpandExpressionException {
EntityGraph<?> entityGraph = null;
if (booleanExpression != null) {
entityGraph = this.expandComponent.getEntityGraph(expandExpression);
}
return this.findOne(identifier, booleanExpression, entityGraph);
}
#Override
public Map<Number, T> findAllRevisions(final BigInteger identifier) {
Assert.notNull(identifier, "The given id must not be null!");
AuditReader auditReader = AuditReaderFactory.get(this.entityManager);
List<Number> revisionList = auditReader.getRevisions(this.jpaEntityInformation.getJavaType(), identifier);
if (revisionList == null || revisionList.isEmpty()) {
return null;
}
Set<Number> revisionSet = new LinkedHashSet<Number>(revisionList);
return auditReader.findRevisions(this.jpaEntityInformation.getJavaType(), revisionSet);
}
#Override
public void delete(Iterable<? extends T> entities) {
super.delete(entities);
super.flush();
}
#Override
public void delete(T entity) {
super.delete(entity);
super.flush();
}
}
public class AbstractCrudService<T extends IdentifiableEntity> implements CrudService<T> {
#Autowired(required=false)
private CrudRepository<T> repository;
#Autowired(required=false)
private NotificationComponent<T> notificationComponent;
private NotificationContext<T> geNotificationContext(String action, List<T> payload) {
DefaultNotificationContext<T> defaultNotificationContext = new DefaultNotificationContext<T>();
/*defaultNotificationContext.setAction(action);
defaultNotificationContext.setObject(this.domainClazz.getSimpleName());
defaultNotificationContext.setInstant(Instant.now());
defaultNotificationContext.setResponsibleId(null);
defaultNotificationContext.setPayload(payload);*/
return defaultNotificationContext;
}
private NotificationContext<T> geNotificationContext(String action, Page<T> payload) {
return geNotificationContext(action, payload.getContent());
}
private NotificationContext<T> geNotificationContext(String action, T payload) {
List<T> payloadList = new ArrayList<T>();
payloadList.add(payload);
return geNotificationContext(action, payloadList);
}
#Override
#Transactional(dontRollbackOn = LongTermRunningException.class)
#TypeTaskCriteria(pre = PreSaveTask.class, post = PostSaveTask.class, referenceGenericType = AbstractCrudService.class)
public List<T> save(List<T> objects)
throws ConcurrentModificationException, UnexpectedException {
List<T> savedObjectList = this.repository.save(objects);
if (this.notificationComponent != null) {
this.notificationComponent.notify(geNotificationContext(NotificationContext.SAVE, savedObjectList));
}
return savedObjectList;
}
#Override
#Transactional(dontRollbackOn = LongTermRunningException.class)
#TypeTaskCriteria(pre = PreSaveTask.class, post = PostSaveTask.class, referenceGenericType = AbstractCrudService.class)
public T save(T object) throws ConcurrentModificationException, UnexpectedException {
T savedObject = this.repository.save(object);
if (this.notificationComponent != null) {
this.notificationComponent.notify(geNotificationContext(NotificationContext.SAVE, savedObject));
}
return savedObject;
}
#Override
#TypeTaskCriteria(pre = PreRetrieveTask.class, post = PostRetrieveTask.class, referenceGenericType = AbstractCrudService.class)
public Page<T> retrieve(
#P(PAGE_NUMBER) final Integer pageNumber,
#P(PAGE_SIZE) final Integer pageSize,
#P(FILTER_EXPRESSION) final String filterExpression,
#P(SORT_EXPRESSION) final String sortExpression,
#P(EXPAND_EXPRESSION) final String expandExpression,
#P(PARAMETERS) final Map<String, String> parameters) throws InvalidParameterException, UnexpectedException {
DefaultRetrieveTaskContext context = TaskContextHolder.getContext();
BooleanExpression booleanExpression = context.getBooleanExpression();
Page<T> page = null;
try {
page = new Page<T>(this.repository.findAll(pageNumber, pageSize, booleanExpression, filterExpression, sortExpression, expandExpression));
} catch (InvalidFilterExpressionException | InvalidSortExpressionException
| InvalidExpandExpressionException e) {
throw new UnexpectedException(e);
}
if (this.notificationComponent != null) {
this.notificationComponent.notify(geNotificationContext(NotificationContext.RETRIEVE, page));
}
return page;
}
#Override
#TypeTaskCriteria(pre = PreRetrieveTask.class, post = PostRetrieveTask.class, referenceGenericType = AbstractCrudService.class)
public T retrieve(BigInteger identifyer, String expandExpression) throws NotFoundException, UnexpectedException {
RetrieveTaskContext context = TaskContextHolder.getContext();
BooleanExpression booleanExpression = context.getBooleanExpression();
T object = null;
try {
object = this.repository.findOne(identifyer, booleanExpression, expandExpression);
} catch (InvalidExpandExpressionException invalidExpandExpressionException) {
throw new UnexpectedException(invalidExpandExpressionException);
}
if (this.notificationComponent != null) {
this.notificationComponent.notify(geNotificationContext(NotificationContext.RETRIEVE, object));
}
return object;
}
#Override
#Transactional(dontRollbackOn = LongTermRunningException.class)
#TypeTaskCriteria(pre = PreDeleteTask.class, post = PostDeleteTask.class, referenceGenericType = AbstractCrudService.class)
public void delete(List<T> objects) throws ConcurrentModificationException, UnexpectedException {
this.repository.delete(objects);
if (this.notificationComponent != null) {
this.notificationComponent.notify(geNotificationContext(NotificationContext.DELETE, (List<T>) null));
}
}
#Override
#Transactional(dontRollbackOn = LongTermRunningException.class)
#TypeTaskCriteria(pre = PreDeleteTask.class, post = PostDeleteTask.class, referenceGenericType = AbstractCrudService.class)
public void delete(T object) throws ConcurrentModificationException, UnexpectedException {
this.repository.delete(object);
if (this.notificationComponent != null) {
this.notificationComponent.notify(geNotificationContext(NotificationContext.DELETE, (T) null));
}
}
}
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(value = "br.org.ccee", repositoryFactoryBeanClass = CrudRepositoryFactoryBean.class)
#EnableAspectJAutoProxy
public class ServiceConfiguration {
#Bean
//#Scope("request")
public ServiceContext serviceContext() {
DefaultServiceContext defaultServiceContext = new DefaultServiceContext();
defaultServiceContext.setInstant(Instant.now());
defaultServiceContext.setUserId(new BigInteger("33"));
defaultServiceContext.setTenantId(new BigInteger("69"));
return defaultServiceContext;
}
#Bean
public TenantEventListener tenantEventListener() {
return new TenantEventListener();
}
#Bean
public AuditEventListener auditEventListener() {
return new AuditEventListener();
}
#Bean
public EventListenerRegistry eventListenerRegistry(
LocalContainerEntityManagerFactoryBean entityManagerFactory,
TenantEventListener tenantEventListener,
AuditEventListener auditEventListener) {
SessionFactoryImpl sessionFactoryImpl = (SessionFactoryImpl) entityManagerFactory.getNativeEntityManagerFactory();
ServiceRegistryImplementor serviceRegistryImplementor = sessionFactoryImpl.getServiceRegistry();
EventListenerRegistry eventListenerRegistry = serviceRegistryImplementor.getService(EventListenerRegistry.class);
eventListenerRegistry.prependListeners(EventType.PRE_INSERT, auditEventListener);
eventListenerRegistry.prependListeners(EventType.PRE_INSERT, tenantEventListener);
eventListenerRegistry.prependListeners(EventType.PRE_UPDATE, auditEventListener);
return eventListenerRegistry;
}
}

public class DefaultCrudRepository<T extends IdentifiableEntity> extends QueryDslJpaRepository<T, BigInteger>
implements CrudRepository<T> {
private static final EntityPathResolver DEFAULT_ENTITY_PATH_RESOLVER = SimpleEntityPathResolver.INSTANCE;
private JpaEntityInformation<T, BigInteger> jpaEntityInformation;
private EntityManager entityManager;
private EntityPath<T> path;
private PathBuilder<T> builder;
private Querydsl querydsl;
#Autowired
private SortComponent sortComponent;
#Autowired
private PageComponent pageComponent;
#Autowired
private FilterComponent filterComponent;
#Autowired
private ExpandComponent expandComponent;

Related

Checkmarx: Unsafe object binding

We are using Java Spring framework. We have an endpoint for passing email object.
#RequestMapping(method = RequestMethod.POST, path = "/api/messaging/v1/emailMessages/actions/send")
String sendEmail(#RequestBody Email email);
Here checkmarx says: The email may unintentionally allow setting the value of cc in LinkedList<>, in the object Email.
Email Object is as follow:
public class Email {
private List<String> bcc = new LinkedList<>();
private List<String> cc = new LinkedList<>();
private String content;
private ContentType contentType = ContentType.TXT;
private String from;
private String returnPath;
private Date sent;
private String subject;
private List<EmailAttachment> attachments = new LinkedList<>();
private List<String> to = new LinkedList<>();
public List<String> getBcc() {
return bcc;
}
public void setBcc(String bcc) {
this.bcc = Collections.singletonList(bcc);
}
public void setBcc(List<String> bcc) {
this.bcc = bcc;
}
public List<String> getCc() {
return cc;
}
public void setCc(String cc) {
this.cc = Collections.singletonList(cc);
}
public void setCc(List<String> cc) {
this.cc = cc;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public ContentType getContentType() {
return contentType;
}
public void setContentType(ContentType contentType) {
this.contentType = contentType;
}
public String getFrom() {
return from;
}
public void setFrom(String from) {
this.from = from;
}
public String getReturnPath() {
return returnPath;
}
public void setReturnPath(String returnPath) {
this.returnPath = returnPath;
}
public Date getSent() {
return sent;
}
public void setSent(Date sent) {
this.sent = sent;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public List<String> getTo() {
return to;
}
public void setTo(String to) {
this.to = Collections.singletonList(to);
}
public void setTo(List<String> to) {
this.to = to;
}
public List<EmailAttachment> getAttachments() {
return attachments;
}
public void setAttachments(List<EmailAttachment> attachments) {
this.attachments = attachments;
}
public boolean equals(Object object) {
boolean equals = false;
if (object instanceof Email) {
Email that = (Email) object;
equals = Objects.equal(this.from, that.from)
&& Objects.equal(this.to, that.to)
&& Objects.equal(this.subject, that.subject)
&& Objects.equal(this.content, that.content);
}
return equals;
}
}
I don't understand these findings, how to solve this.
I have added Lombok with #Getter & #Setter annotation to resolve this issue.

Replace OAuth2AccessTokenJackson2Deserializer with my own custom deserializer

This class is deserializing an oauth2 token and I would like to tweak it. I created my own class extending StdDeserializer<OAuth2AccessToken> which at the moment is the same as the original class.
Here is the class:
public class MyCustomDeserializer extends StdDeserializer<OAuth2AccessToken> {
public MyCustomDeserializer() {
super(OAuth2AccessToken.class);
}
#Override
public OAuth2AccessToken deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException,
JsonProcessingException {
String tokenValue = null;
String tokenType = null;
String refreshToken = null;
Long expiresIn = null;
Set<String> scope = null;
Map<String, Object> additionalInformation = new LinkedHashMap<String, Object>();
// TODO What should occur if a parameter exists twice
while (jp.nextToken() != JsonToken.END_OBJECT) {
String name = jp.getCurrentName();
jp.nextToken();
if (OAuth2AccessToken.ACCESS_TOKEN.equals(name)) {
tokenValue = jp.getText();
}
else if (OAuth2AccessToken.TOKEN_TYPE.equals(name)) {
tokenType = jp.getText();
}
else if (OAuth2AccessToken.REFRESH_TOKEN.equals(name)) {
refreshToken = jp.getText();
}
else if (OAuth2AccessToken.EXPIRES_IN.equals(name)) {
try {
expiresIn = jp.getLongValue();
} catch (JsonParseException e) {
expiresIn = Long.valueOf(jp.getText());
}
}
else if (OAuth2AccessToken.SCOPE.equals(name)) {
scope = parseScope(jp);
} else {
additionalInformation.put(name, jp.readValueAs(Object.class));
}
}
// TODO What should occur if a required parameter (tokenValue or tokenType) is missing?
DefaultOAuth2AccessToken accessToken = new DefaultOAuth2AccessToken(tokenValue);
accessToken.setTokenType(tokenType);
if (expiresIn != null) {
accessToken.setExpiration(new Date(System.currentTimeMillis() + (expiresIn * 1000)));
}
if (refreshToken != null) {
accessToken.setRefreshToken(new DefaultOAuth2RefreshToken(refreshToken));
}
accessToken.setScope(scope);
accessToken.setAdditionalInformation(additionalInformation);
return accessToken;
}
private Set<String> parseScope(JsonParser jp) throws JsonParseException, IOException {
Set<String> scope;
if (jp.getCurrentToken() == JsonToken.START_ARRAY) {
scope = new TreeSet<String>();
while (jp.nextToken() != JsonToken.END_ARRAY) {
scope.add(jp.getValueAsString());
}
} else {
String text = jp.getText();
scope = OAuth2Utils.parseParameterList(text);
}
return scope;
}
}
Here I am registering the bean:
#Bean
public ObjectMapper configObjectMapper() {
final ObjectMapper objectMapper = new ObjectMapper();
objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
final SimpleModule module = new SimpleModule("configModule", com.fasterxml.jackson.core.Version.unknownVersion());
module.addDeserializer(OAuth2AccessToken.class, new MyCustomDeserializer());
objectMapper.registerModule(module);
return objectMapper;
}
Testing the above code the flow doesn't reach my class but the original. I am using spring boot 2.1.4

JUnit/Spring/MongoDB: Unit test fails due to null value

I am fairly new to unit test and started writing a simple test to make sure the returned query is not null using assertJ. I am using Fongo for my unit test and although I am having no error, the returned value is always null.
This is the class to be tested:
#Repository
public class DataVersionDaoMongo extends MongoBaseDao<DataVersion> implements DataVersionDao {
#Autowired
MongoOperations mongoOperations;
public DataVersionDaoMongo() {
initType();
}
#Override
public DataVersion findByDBAndCollection(String dbName, String collectionName) {
//return mongoOperations.findOne(Query.query(Criteria.where("dbName").is(dbName).and("collectionName").is(collectionName)), DataVersion.class);
Criteria criteria = Criteria.where("dbName").is(dbName).and("collectionName").is(collectionName);
Query query = Query.query(criteria);
return mongoOperations.findOne(query, DataVersion.class);
}
}
This is my unit test:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("classpath:/testApplicationContext.xml")
public class DataVersionDaoMongoTest {
#Autowired
private DataVersionDaoMongo dataVersionDaoMongo;
//private MongoOperations mongoOperations;
private DataVersion dataVersion;
#Rule
public FongoRule fongoRule = new FongoRule();
#Test
public void findByDBAndCollection() {
String dbname = "mydb";
String collectionName = "mycollection";
DB db = fongoRule.getDB(dbname);
DBCollection collection = db.getCollection(collectionName);
Mongo mongo = fongoRule.getMongo();
collection.insert(new BasicDBObject("name", "randomName"));
assertThat(dataVersionDaoMongo.findByDBAndCollection(dbname, collectionName)).isNotNull();
}
}
I am sure that
dataVersionDaoMongo.findByDBAndCollection(dbname, collectionName) is returning null (It is returning DataVersion object which is null), so the test fails. How would I actually go about and make it return DataVersion that is not null?
Here is the DataVersion class:
#Document(collection = "DataVersion")
public class DataVersion {
#Id
private String id;
private String dbName;
private String collectionName;
private String version;
private boolean isCompleted;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getDbName() {
return dbName;
}
public void setDbName(String dbName) {
this.dbName = dbName;
}
public String getCollectionName() {
return collectionName;
}
public void setCollectionName(String collectionName) {
this.collectionName = collectionName;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public boolean isCompleted() {
return isCompleted;
}
public void setCompleted(boolean isCompleted) {
this.isCompleted = isCompleted;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((collectionName == null) ? 0 : collectionName.hashCode());
result = prime * result + ((dbName == null) ? 0 : dbName.hashCode());
result = prime * result + (isCompleted ? 1231 : 1237);
result = prime * result + ((version == null) ? 0 : version.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
DataVersion other = (DataVersion) obj;
if (collectionName == null) {
if (other.collectionName != null)
return false;
} else if (!collectionName.equals(other.collectionName))
return false;
if (dbName == null) {
if (other.dbName != null)
return false;
} else if (!dbName.equals(other.dbName))
return false;
if (isCompleted != other.isCompleted)
return false;
if (version == null) {
if (other.version != null)
return false;
} else if (!version.equals(other.version))
return false;
return true;
}
}
Any help would be greatly appreciated!
P.S.
This is what I am adding in my unit test class:
#Autowired
private MongoOperations mongoOperations;
Then
DataVersion dataVersion = new DataVersion();
dataVersion.setDbName("DBDataVersion");
dataVersion.setVersion("version1");
dataVersion.setCollectionName("DataVersion");
mongoOperations.insert(dataVersion);
assertThat(dataVersionDaoMongo.findByDBAndCollection(dataVersionDaoMongo.getDbName(), dataVersion.getCollectionName())).isNotNull();
The unit test passes because it is no longer returning null, but then I am not making use of Fongo anymore. I am not sure if what I am doing is right or not.
You insert the document into mycollection collection in the test but the dao queries DataVersion collection.
Also you don't define dbName and collectionName in the stored object, hence, it won't be picked by a query which targets that two fields.

how to add entity listener programmable in Hibernate JPA

I use spring, hibernate, jpa2.1.
as follow:
#Entity
#EntityListeners(DemoListener.class)
public class Demo {
#Id
private Long id;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
}
public class DemoListener {
#PersistenceContext
private EntityManager entityManager;
#PrePersist
public void prePersist(Demo demo){
}
}
the example works well, when I want to add more listener, I must modify the Demo entity, but the Demo is in other jar,I don't want to use the XML configuration, is there some way like this:
...addListener(Demo.class, new DemoListener());
...addListener(Demo.class, new OtherDemoListener());
base on hibernate-orm docs and hibernate-tutorials:
/**
* #param <T> one of {#link EventType#baseListenerInterface()}
* #see org.hibernate.event.service.spi.EventListenerRegistry
*/
public interface JpaEventListenerRegistry<T> {
/**
* add listener for entity class
*
* #param entityClass can't be null
* #param listener can't be null
*/
void addListener(Class<?> entityClass, T listener);
}
public class JpaEventListenerRegistryImpl implements JpaEventListenerRegistry<Object> {
private Logger logger = LoggerFactory.getLogger(getClass());
private EventListenerRegistry eventListenerRegistry;
private Map<EventType, JpaEventListenerRegistry> listeners = new HashMap<EventType, JpaEventListenerRegistry>();
public JpaEventListenerRegistryImpl(EventListenerRegistry eventListenerRegistry) {
this.eventListenerRegistry = eventListenerRegistry;
initDefault();
}
private void initDefault() {
listeners.put(EventType.PRE_INSERT, new DomainPreInsertEventListener());
listeners.put(EventType.POST_INSERT, new DomainPostInsertEventListener());
for (Map.Entry<EventType, JpaEventListenerRegistry> entry : listeners.entrySet()) {
eventListenerRegistry.appendListeners(entry.getKey(), entry.getValue());
}
}
#SuppressWarnings("unchecked")
public void addListener(Class<?> entityClass, Object listener) {
logger.info("add listener {} for entity {}", listener, entityClass.getName());
for (EventType eventType : EventType.values()) {
Class<?> listenerInterface = eventType.baseListenerInterface();
if (listenerInterface.isAssignableFrom(listener.getClass())) {
JpaEventListenerRegistry registry = listeners.get(eventType);
if (registry == null) {
logger.warn("the event type {} for listener {} is not supported", eventType, listener);
} else {
registry.addListener(entityClass, listener);
}
}
}
}
public static class Abstract<T> implements JpaEventListenerRegistry<T> {
private Logger logger = LoggerFactory.getLogger(getClass());
private Map<Class<?>, List<T>> listeners = new HashMap<Class<?>, List<T>>();
public void addListener(Class<?> entityClass, T listener) {
logger.info("add listener {} for entity {}", listener, entityClass.getName());
List<T> listeners = this.listeners.get(entityClass);
if (listeners == null) {
listeners = new ArrayList<T>();
this.listeners.put(entityClass, listeners);
}
listeners.add(listener);
}
List<T> findListener(Class<?> entityClass) {
for (Map.Entry<Class<?>, List<T>> entry : listeners.entrySet()) {
if (entry.getKey().isAssignableFrom(entityClass)) {
return entry.getValue();
}
}
return null;
}
}
public static class DomainPreInsertEventListener extends Abstract<PreInsertEventListener> implements PreInsertEventListener {
public boolean onPreInsert(PreInsertEvent event) {
return onPreInsert(event, findListener(event.getEntity().getClass()));
}
private boolean onPreInsert(PreInsertEvent event, List<PreInsertEventListener> listeners) {
if (listeners == null) return false;
for (PreInsertEventListener listener : listeners) {
if (listener.onPreInsert(event)) return true;
}
return false;
}
}
public static class DomainPostInsertEventListener extends Abstract<PostInsertEventListener> implements PostInsertEventListener {
public void onPostInsert(PostInsertEvent event) {
onPostInsert(event, findListener(event.getEntity().getClass()));
}
private void onPostInsert(PostInsertEvent event, List<PostInsertEventListener> listeners) {
if (listeners == null) return;
for (PostInsertEventListener listener : listeners) {
listener.onPostInsert(event);
}
}
public boolean requiresPostCommitHanding(EntityPersister persister) {
return false;
}
}
}
public class EntityManagerIllustrationTest extends TestCase {
private EntityManagerFactory entityManagerFactory;
#Override
protected void setUp() throws Exception {
// like discussed with regards to SessionFactory, an EntityManagerFactory is set up once for an application
// IMPORTANT: notice how the name here matches the name we gave the persistence-unit in persistence.xml!
entityManagerFactory = Persistence.createEntityManagerFactory("org.hibernate.tutorial.jpa");
SessionFactoryImplementor sessionFactory = entityManagerFactory.unwrap(SessionFactoryImplementor.class);
EventListenerRegistry eventListenerRegistry = sessionFactory.getServiceRegistry().getService(EventListenerRegistry.class);
JpaEventListenerRegistryImpl jpaEventListenerRegistry = new JpaEventListenerRegistryImpl(eventListenerRegistry);
jpaEventListenerRegistry.addListener(EventListener.class, new JpaEventListener());
}
private static class JpaEventListener implements PreInsertEventListener, PostInsertEventListener {
public boolean onPreInsert(PreInsertEvent event) {
Event entity = (Event) event.getEntity();
System.out.println("onPreInsert:" + entity);
return false;
}
public void onPostInsert(PostInsertEvent event) {
Event entity = (Event) event.getEntity();
System.out.println("onPostInsert:" + entity);
}
public boolean requiresPostCommitHanding(EntityPersister persister) {
return false;
}
}
#Override
protected void tearDown() throws Exception {
entityManagerFactory.close();
}
public void testBasicUsage() {
// create a couple of events...
EntityManager entityManager = entityManagerFactory.createEntityManager();
entityManager.getTransaction().begin();
entityManager.persist(new Event("Our very first event!", new Date()));
// entityManager.persist(new Event("A follow up event", new Date()));
entityManager.getTransaction().commit();
entityManager.close();
// now lets pull events from the database and list them
entityManager = entityManagerFactory.createEntityManager();
entityManager.getTransaction().begin();
List<Event> result = entityManager.createQuery("from Event", Event.class).getResultList();
for (Event event : result) {
System.out.println("Event (" + event.getDate() + ") : " + event.getTitle());
}
entityManager.getTransaction().commit();
entityManager.close();
}
}

java 8 nested null check list of objects

I am trying to do a nested null check and then clear the values in map in the nested object if the map is not null.
The following is my hypothetical code. I am wondering if this is the right way to do it or is there a more elegant solution to this.
package exp.myJavaLab.Experiments;
import java.util.*;
public class OptionalTest {
public Inner inner;
public static void main(String[] args) {
OptionalTest testObj = new OptionalTest();
Pojo pojo1 = new Pojo();
pojo1.id = 1;
Map<String, String> dataMap = new HashMap<>();
dataMap.put("a","b");
pojo1.dataMap = dataMap;
Pojo pojo2 = new Pojo();
pojo2.id = 2;
Inner inner = new Inner();
inner.pojoList = Arrays.asList(pojo1, pojo2);
testObj.inner = inner;
System.out.println(testObj);
Optional.ofNullable(testObj.inner)
.map(Inner::getPojoList)
.ifPresent(pojos -> pojos.forEach(pojo -> {
if (pojo.getDataMap() != null) {
pojo.getDataMap().clear();
}
}));
System.out.println(testObj);
}
#Override
public String toString() {
final StringBuilder sb = new StringBuilder("OptionalTest{");
sb.append("inner=").append(inner);
sb.append('}');
return sb.toString();
}
}
class Inner {
public List<Pojo> pojoList;
public List<Pojo> getPojoList() {
return pojoList;
}
#Override
public String toString() {
final StringBuilder sb = new StringBuilder("Inner{");
sb.append("pojoList=").append(pojoList);
sb.append('}');
return sb.toString();
}
}
class Pojo {
public Map<String, String> dataMap;
public int id;
#Override
public String toString() {
final StringBuilder sb = new StringBuilder("Pojo{");
sb.append("dataMap=").append(dataMap);
sb.append(", id=").append(id);
sb.append('}');
return sb.toString();
}
public Map<String, String> getDataMap() {
return dataMap;
}
public int getId() {
return id;
}
}
In my opinion Collections should never be null.
You could declare your pojoList and dataMap as private and instantiate them.
Your class then needs some add-methods. So you are sure getDataMap() never returns null:
class Pojo {
private Map<String, String> dataMap = new HashMap<>();
public Map<String, String> getDataMap() {
return dataMap;
}
public void add(String key, String value) {
dataMap.put(key, value);
}
}
Then you don't need to check for null:
Optional.ofNullable(testObj.inner)
.map(Inner::getPojoList)
.ifPresent(pojos -> pojos.forEach(pojo -> { pojo.getDataMap().clear(); }));

Resources