Got a huge problem with quartz Job in Confluence, regarding the page creation.
QUARTZ Job class:
#ComponentImport
private final SpaceManager spaceManager;
#Autowired
private final GeneralConfig config;
#Autowired
private final PageCreator pageCreator;
#ComponentImport
private final PageManager pageManager;
#Autowired
public ReportingPluginJob(GeneralConfig config, SpaceManager spaceManager, PageCreator pageCreator,
PageManager pageManager) {
this.config = config;
this.spaceManager = spaceManager;
this.pageCreator = pageCreator;
this.pageManager = pageManager;
}
private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(ReportingPluginJob.class);
#Override
public void execute(JobExecutionContext jec) throws JobExecutionException {
Collection<String> keys = spaceManager.getAllSpaceKeys(SpaceStatus.CURRENT);
String parentPageName = config.getSchedulerWeeklyParentPageName();
for (String key : keys) {
Page parentPage
= pageManager.getPage(key, parentPageName);
if (parentPage != null) {
LOG.debug("Creating weekly report for space " + key);
long pageId = parentPage.getId();
try {
pageCreator.createEazyBiReport(key, pageId);
} catch (ApplicationException e) {
LOG.error("FAILED TO CREATE A REPORT FOR SPACE " + key + " with error: " + System.lineSeparator()
+ e.getMessage());
}
}
}
}
PAGE CREATION class:
Space space = spaceManager.getSpace(spaceKey);
if (page != null) {
page.setTitle(pageTitle);
page.setSpace(space);
page.setVersion(1);
page.addLabelling(new Labelling(label, page.getEntity(), AuthenticatedUserThreadLocal.get()));
page.setCreator(AuthenticatedUserThreadLocal.get());
page.setCreationDate(new Date());
Page parent = pageManager.getPage(parentId);
if (parent != null) {
parent.addChild(page);
}
}
pageManager.saveContentEntity(page, DefaultSaveContext.builder().suppressNotifications(true).build());
attachmentProvider.attachExcelFileToPage(page);
AND Finally the exception which is driving me mad:
org.springframework.dao.DuplicateKeyException: A different object with the same identifier value was already associated with the session : [com.atlassian.confluence.spaces.Space#31653891]; nested exception is org.hibernate.NonUniqueObjectException: A different object with the same identifier value was already associated with the session : [com.atlassian.confluence.spaces.Space#31653891]
at org.springframework.orm.hibernate5.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:259)
at org.springframework.orm.hibernate5.HibernateTemplate.doExecute(HibernateTemplate.java:362)
at org.springframework.orm.hibernate5.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:326)
at org.springframework.orm.hibernate5.HibernateTemplate.saveOrUpdate(HibernateTemplate.java:704)
at com.atlassian.confluence.core.persistence.hibernate.HibernateObjectDao.saveRaw(HibernateObjectDao.java:207)
at com.atlassian.confluence.pages.persistence.dao.hibernate.CachingPageDao.saveRaw(CachingPageDao.java:157)
at com.atlassian.confluence.core.DefaultContentEntityManager.saveContentEntity(DefaultContentEntityManager.java:150)
at com.atlassian.confluence.pages.DefaultPageManager.saveContentEntity(DefaultPageManager.java:1388)
at sun.reflect.GeneratedMethodAccessor2132.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:302)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at com.atlassian.spring.interceptors.SpringProfilingInterceptor.invoke(SpringProfilingInterceptor.java:16)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at com.atlassian.confluence.util.profiling.ConfluenceMonitoringMethodInterceptor.invoke(ConfluenceMonitoringMethodInterceptor.java:34)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208)
at com.sun.proxy.$Proxy105.saveContentEntity(Unknown Source)
at sun.reflect.GeneratedMethodAccessor2132.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.atlassian.plugin.util.ContextClassLoaderSettingInvocationHandler.invoke(ContextClassLoaderSettingInvocationHandler.java:26)
at com.sun.proxy.$Proxy253.saveContentEntity(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:302)
at org.eclipse.gemini.blueprint.service.importer.support.internal.aop.ServiceInvoker.doInvoke(ServiceInvoker.java:56)
at org.eclipse.gemini.blueprint.service.importer.support.internal.aop.ServiceInvoker.invoke(ServiceInvoker.java:60)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:133)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:121)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.eclipse.gemini.blueprint.service.util.internal.aop.ServiceTCCLInterceptor.invokeUnprivileged(ServiceTCCLInterceptor.java:70)
at org.eclipse.gemini.blueprint.service.util.internal.aop.ServiceTCCLInterceptor.invoke(ServiceTCCLInterceptor.java:53)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.eclipse.gemini.blueprint.service.importer.support.LocalBundleContextAdvice.invoke(LocalBundleContextAdvice.java:57)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:133)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:121)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208)
at com.sun.proxy.$Proxy2863.saveContentEntity(Unknown Source)
at com.censored.atlassian.plugins.service.PageCreator.createEazyBiReport(PageCreator.java:128)
at com.censored.atlassian.plugins.service.ReportingPluginJob.execute(ReportingPluginJob.java:64)
at com.atlassian.confluence.plugin.descriptor.JobModuleDescriptor$DelegatingPluginJob.lambda$execute$0(JobModuleDescriptor.java:113)
at com.atlassian.confluence.impl.vcache.VCacheRequestContextManager.doInRequestContextInternal(VCacheRequestContextManager.java:87)
at com.atlassian.confluence.impl.vcache.VCacheRequestContextManager.doInRequestContext(VCacheRequestContextManager.java:71)
at com.atlassian.confluence.plugin.descriptor.JobModuleDescriptor$DelegatingPluginJob.execute(JobModuleDescriptor.java:112)
at org.quartz.core.JobRunShell.run(JobRunShell.java:223)
at com.atlassian.confluence.schedule.quartz.ConfluenceQuartzThreadPool.lambda$runInThread$0(ConfluenceQuartzThreadPool.java:16)
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:549)
According the stack trace, I've got a problem during the page save (saveContentEntity). It seems, the page save needs to update a space associated with the page too.
And here comes the problem. According to the stack trace, this space exists in the Hibernate session already. evict and clear of the actual session does not work.
Any suggestions, how can I handle this exception, or how can I actually remove the space from Hibernate session?
Apparently, this is what's happening in your code:
Within your SpaceManager, your session finds a Session object with ID 1 (assume that) and returns it.
Your method uses this reference to associate with another object, a Page one.
And finally, your PageManager persist this data in the database.
Probably, your problem is problem that:
From step 1 to 2, when the SpaceManager returns the data, your transaction is ended and your returned object becomes detached.
After that, when you call save, you are trying to persist a detached Session, but it already exists in the database. Then you get an exception.
You could try to use the merge method or remove the cascade from this reference in your entity.
(Please provide your entity code so I can improve my answer if there's anything wrong or which don't work for you.)
We ran into the same problem and what solved it for us was to put the code that creates the page (and loads other objects, like the space or the parent page) all into a transaction:
private void createNewPage(String title, String pageInput, Long parentPageId, String spaceKey) {
transactionTemplate.execute(() -> {
Page page = new Page();
page.setTitle(title);
page.setBodyAsString(pageInput);
Space space = spaceManager.getSpace(spaceKey);
page.setSpace(space);
Page parentPage = pageManager.getPage(parentPageId);
if (parentPage != null) {
page.setParentPage(parentPage);
parentPage.addChild(page);
}
pageManager.saveContentEntity(page, DefaultSaveContext.DEFAULT);
return null;
});
}
com.atlassian.sal.api.transaction.TransactionTemplate can be injected with #ComponentImport
Related
I want to get serial numbers with the help of database.
Here is what I want:
1.read the entity from database and lock it
2.increase the serial number and upadte the entity.
I am asuming the first thread can lock the record and the other thread won't work until the first thread commits its transaction, however, I got the opposite of what I want.
below is my code:
Repository:
public interface ActivityNoGeneratorRepository extends BaseRepository<ActivityNoGenerator, Long> {
#Lock(LockModeType.PESSIMISTIC_WRITE)
#Query(value = "select generator from ActivityNoGenerator generator where id=:id")
ActivityNoGenerator getGeneratorByIdForUpdate(#Param("id") Long id);
}
Service:
#Service
public class ActivityNoGeneratorServiceImpl implements IActivityNoGeneratorService {
#Autowired
private ActivityNoGeneratorRepository activityNoGeneratorRepository;
#Override
#Transactional
public String getActivityNo() {
ActivityNoGenerator activityNoGenerator = activityNoGeneratorRepository.getGeneratorByIdForUpdate(1L);
System.out.println(1);
Integer currentValue = activityNoGenerator.getCurrentValue() + 1;
if (!StringUtils.equals(DateFormatUtils.format(new Date(), "yyyyMM"), DateFormatUtils.format(activityNoGenerator.getLastAccessTime(), "yyyyMM"))) {
currentValue = 1;
}
String serialNum = String.format("%0" + activityNoGenerator.getWidth() + "d", currentValue);
String activityNo = activityNoGenerator.getPrefix() + activityNoGenerator.getPlatformCode() + DateFormatUtils.format(new Date(), "yyyyMM") + serialNum;
activityNoGenerator.setCurrentValue(currentValue);
activityNoGenerator.setLastAccessTime(new Date());
activityNoGeneratorRepository.save(activityNoGenerator);
return activityNo;
}
}
Test:
public class IActivityNoGeneratorServiceTest {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath*:spring/applicationContext.xml");
final IActivityNoGeneratorService activityNoGeneratorService = applicationContext.getBean(IActivityNoGeneratorService.class);
for (int i = 0; i < 2; i++) {
new Thread(new Runnable() {
#Override
public void run() {
System.out.println(activityNoGeneratorService.getActivityNo());
}
}).start();
}
}
}
Result:
Hibernate:
select
activityno0_.id as id1_3_,
activityno0_.current_value as current_2_3_,
activityno0_.last_access_time as last_acc3_3_,
activityno0_.platform_code as platform4_3_,
activityno0_.platform_name as platform5_3_,
activityno0_.prefix as prefix6_3_,
activityno0_.step as step7_3_,
activityno0_.width as width8_3_
from
activity_no_generator activityno0_
where
activityno0_.id=? for update
Hibernate:
select
activityno0_.id as id1_3_,
activityno0_.current_value as current_2_3_,
activityno0_.last_access_time as last_acc3_3_,
activityno0_.platform_code as platform4_3_,
activityno0_.platform_name as platform5_3_,
activityno0_.prefix as prefix6_3_,
activityno0_.step as step7_3_,
activityno0_.width as width8_3_
from
activity_no_generator activityno0_
where
activityno0_.id=? for update
1
1
Hibernate:
update
activity_no_generator
set
current_value=?,
last_access_time=?,
platform_code=?,
platform_name=?,
prefix=?,
step=?,
width=?
where
id=?
Hibernate:
update
activity_no_generator
set
current_value=?,
last_access_time=?,
platform_code=?,
platform_name=?,
prefix=?,
step=?,
width=?
where
id=?
Exception in thread "Thread-6" org.springframework.orm.jpa.JpaSystemException: commit failed; nested exception is org.hibernate.TransactionException: commit failed
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:333)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:244)
at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:521)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:761)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:730)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:483)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:290)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
at com.sun.proxy.$Proxy44.getActivityNo(Unknown Source)
at com.lemall.srd.pop.activity.oa.service.IActivityNoGeneratorServiceTest$1.run(IActivityNoGeneratorServiceTest.java:18)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.hibernate.TransactionException: commit failed
at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:187)
at org.hibernate.jpa.internal.TransactionImpl.commit(TransactionImpl.java:77)
at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:517)
... 10 more
Caused by: org.hibernate.TransactionException: unable to commit against JDBC connection
at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.doCommit(JdbcTransaction.java:116)
at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:180)
... 12 more
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:404)
at com.mysql.jdbc.Util.getInstance(Util.java:387)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:950)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3966)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3902)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2526)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2673)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2545)
at com.mysql.jdbc.ConnectionImpl.commit(ConnectionImpl.java:1614)
at com.zaxxer.hikari.pool.ProxyConnection.commit(ProxyConnection.java:355)
at com.zaxxer.hikari.pool.HikariProxyConnection.commit(HikariProxyConnection.java)
at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.doCommit(JdbcTransaction.java:112)
... 13 more
HD1020012017050631
Process finished with exit code 0
I debug my code and find the second thread executed without waiting the first thread commit.
Any clue what mistake I make? Thanks very much!
What I see is that you are missing the #Transactional annotation in your repository method which might be the reason that your service method and repo method are running in two different transactions. Also use the Propagation.Required option in your transactional annotation.
While using SpringBoot with MSSQL server stored proc, when the value is null, Stored proc fails to execute. the value have default as null while calling.
If the parameters are excluded, the proc works. But as these are optional parameters, what are my options to call the stored proc?
When i try to pass null while calling the stored procedure, it is failing with this error.
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessResourceUsageException: Error calling CallableStatement.getMoreResults; SQL [saveInfo]; nested exception is org.hibernate.exception.SQLGrammarException: Error calling CallableStatement.getMoreResults] with root cause
java.sql.SQLException: Parameter #1 has not been set.
at net.sourceforge.jtds.jdbc.TdsCore.executeSQL(TdsCore.java:1049)
at net.sourceforge.jtds.jdbc.JtdsStatement.executeSQL(JtdsStatement.java:563)
at net.sourceforge.jtds.jdbc.JtdsPreparedStatement.execute(JtdsPreparedStatement.java:787)
at org.hibernate.result.internal.OutputsImpl.<init>(OutputsImpl.java:52)
at org.hibernate.procedure.internal.ProcedureOutputsImpl.<init>(ProcedureOutputsImpl.java:32)
at org.hibernate.procedure.internal.ProcedureCallImpl.buildOutputs(ProcedureCallImpl.java:411)
at org.hibernate.procedure.internal.ProcedureCallImpl.getOutputs(ProcedureCallImpl.java:363)
at org.hibernate.jpa.internal.StoredProcedureQueryImpl.outputs(StoredProcedureQueryImpl.java:234)
at org.hibernate.jpa.internal.StoredProcedureQueryImpl.execute(StoredProcedureQueryImpl.java:217)
at com.tda.etfmc.service.repository.ETFMgmtRepository.saveCommissionFreeETF(ETFMgmtRepository.java:87)
at com.tda.etfmc.service.repository.ETFMgmtRepository$$FastClassBySpringCGLIB$$d1d68142.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:721)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:282)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:656)
StoredProc:
CREATE PROCEDURE [dbo].[saveInfo]
#input1 varchar(16) = NULL,
#input2 varchar(16) = NULL
AS
BEGIN
//do save here
END
GO
#Repository
public class MyRepository {
private EntityManager entityManager;
public MyRepository(EntityManager entityManager) {
this.entityManager = entityManager;
}
#Procedure(name = "saveInfo")
#Transactional
public void saveInfo(List<Input> inputList) throws SQLException {
StoredProcedureQuery saveInfo;
for (Input input : inputList) {
saveInfo = entityManager.createNamedStoredProcedureQuery("saveInfo");
saveInfo.setParameter("input1", input.getInput1());// pass null here
saveInfo.setParameter("input2", input.getInput2());
saveInfo.execute();
}
}
}
#Data
#NamedStoredProcedureQuery(name = "saveInfo", procedureName = "saveInfo", parameters = {
#StoredProcedureParameter(name = "input1", type = String.class, mode = ParameterMode.IN),
#StoredProcedureParameter(name = "input2", type = String.class, mode = ParameterMode.IN) })
class Input implements Serializable {
private static final long serialVersionUID = 1L;
#Column(name = "#input1")
private String input1;
#Column(name = "#input2")
private String input2;
}
Just want to call Stored procedure of SQL server from java using Hibernate as ORM.
The stored Procedure has so many result set which I am keeping it in Java as DTO's and each one as list in one DTO to send as JSON payload for Front-end integration.
But I am getting exception saying"org.hibernate.MappingException: Unknown entity: com.test.plans.dto.TemplatesDTO"
public ItemDetailsDTO getItemDetails(int no) {
Session session = getSession();
Connection connection = null;
List<ItemDetailsDTO> resultList = new ArrayList<>();
try {
ResultSet rs = null;
SessionImpl sessionImpl = (SessionImpl) session;
connection = sessionImpl.connection();
Query query = session.createSQLQuery("exec usp_GetItemDetails :no")
.addEntity(TemplatesDTO.class)
.setParameter("no", no);
resultList = query.list();
} catch (Exception e) {
System.out.println("error");
e.printStackTrace();
}
return resultList.get(0);
}
DTO :
import java.util.List;
public class ItemDetailsDTO {
private List<TemplatesDTO> templates;
public List<TemplatesDTO> gettemplates() {
return templates;
}
public void settemplates(List<TemplatesDTO> templates) {
this.templates = templates;
}
}
Please find below complete trace of exception
org.hibernate.MappingException: Unknown entity: com.test.plans.dto.TemplatesDTO
at org.hibernate.internal.SessionFactoryImpl.getEntityPersister(SessionFactoryImpl.java:783)
at org.hibernate.loader.custom.sql.SQLQueryReturnProcessor.getSQLLoadable(SQLQueryReturnProcessor.java:358)
at org.hibernate.loader.custom.sql.SQLQueryReturnProcessor.processRootReturn(SQLQueryReturnProcessor.java:411)
at org.hibernate.loader.custom.sql.SQLQueryReturnProcessor.processReturn(SQLQueryReturnProcessor.java:378)
at org.hibernate.loader.custom.sql.SQLQueryReturnProcessor.process(SQLQueryReturnProcessor.java:180)
at org.hibernate.loader.custom.sql.SQLCustomQuery.(SQLCustomQuery.java:71)
at org.hibernate.engine.query.internal.NativeQueryInterpreterStandardImpl.createQueryPlan(NativeQueryInterpreterStandardImpl.java:70)
at org.hibernate.engine.query.spi.QueryPlanCache.getNativeSQLQueryPlan(QueryPlanCache.java:210)
at org.hibernate.internal.AbstractSessionImpl.getNativeSQLQueryPlan(AbstractSessionImpl.java:306)
at org.hibernate.internal.AbstractSessionImpl.list(AbstractSessionImpl.java:322)
at org.hibernate.internal.SQLQueryImpl.list(SQLQueryImpl.java:125)
at nbcu.compass.contingencyplans.dao.impl.ContDAOImpl.getItemDetails(ContingencyDAOImpl.java:503)
at nbcu.compass.contingencyplans.dao.impl.ContDAOImpl$$FastClassBySpringCGLIB$$c2b97106.invoke()
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:720)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:655)
at com.test.plans.dao.impl.ContDAOImpl$$EnhancerBySpringCGLIB$$a1741e1f.getItemDetails()
at com.test.plans.service.impl.ContPlanServiceImpl.getConditionScheduleItemDetails(ContingencyPlanServiceImpl.java:316)
at test.plans.plans.rest.impl.PlanResourceImpl.getItemDetails(PlanResourceImpl.java:87)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:114)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
I'm implementing an object that represents a graph to be stored in a MongoDb. Here's the class definition:
#Document(collection = "mygraph")
public class MyGraph {
#Id
#JsonSerialize(using = ToStringSerializer.class)
public String id;
public Map<Instance, Set<Instance>> graph;
public String timestamp;
/**
* Add the default constructor
*/
public MyGraph() {
this.id = new ObjectId().toHexString();
this.graph = new LinkedHashMap<>();
DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
this.timestamp = dateFormat.format(new Date());
}
/**
*
* #param instances
*/
public MyGraph(Set<Instance> instances) {
this.id = new ObjectId().toHexString();
this.graph = new LinkedHashMap<>();
DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
this.timestamp = dateFormat.format(new Date());
/* Initialize the graph */
for (Instance instance : instances) {
this.graph.put(instance, new HashSet<>());
}
}
// get and set method are below
}
However I'm getting the following error:
Time elapsed: 0.03 sec <<< FAILURE!
org.springframework.data.mapping.model.MappingException: Cannot use a complex object as a key value.
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.writeMapInternal(MappingMongoConverter.java:669)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.createMap(MappingMongoConverter.java:585)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.writePropertyInternal(MappingMongoConverter.java:471)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter$3.doWithPersistentProperty(MappingMongoConverter.java:430)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter$3.doWithPersistentProperty(MappingMongoConverter.java:418)
at org.springframework.data.mapping.model.BasicPersistentEntity.doWithProperties(BasicPersistentEntity.java:312)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.writeInternal(MappingMongoConverter.java:418)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.writeInternal(MappingMongoConverter.java:392)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.write(MappingMongoConverter.java:356)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.write(MappingMongoConverter.java:79)
at org.springframework.data.mongodb.core.MongoTemplate.toDbObject(MongoTemplate.java:853)
at org.springframework.data.mongodb.core.MongoTemplate.doSave(MongoTemplate.java:1014)
at org.springframework.data.mongodb.core.MongoTemplate.save(MongoTemplate.java:963)
at org.springframework.data.mongodb.repository.support.SimpleMongoRepository.save(SimpleMongoRepository.java:80)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:503)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:488)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:460)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:61)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
at com.sun.proxy.$Proxy197.save(Unknown Source)
at models.CloudGraphTest.testSaveCloudGraph(CloudGraphTest.java:79)
How can I change my MappingMongoConverter to accomodate for that?
There's an open Improvement in Spring: Don't require Converters for Complex classes that are used as Ids.
Unfortunately, currently Spring team decided not to support it.
decided not to support it at all
EDIT
There's an open related issue Allow using complex types as Map keys that may include a fix later
Please help in multithreaded scenario rarely I get NullPointerException in below code
public class CassPerfInterceptor {
private static final Logger log = LoggerFactory
.getLogger(CassPerfInterceptor.class);
private Performance performance;
#Autowired
private QueueServerMbean queueServerMbean;
#Around("target(org.springframework.data.repository.CrudRepository) || execution(public * com.owmessaging.*.dao.*.*Dao.*(..))")
public Object invoke(ProceedingJoinPoint joinPoint) throws Throwable {
long start = System.currentTimeMillis();
try {
Object obj = joinPoint.proceed();
performance = StatsProvider.getCassandraStats(joinPoint.getSignature().getName());
if(performance != null){
// Here I am getting NPE line number 30
performance.add(System.currentTimeMillis()-start, false);
}
return obj;
}catch(DriverException de){
queueServerMbean.sendNotification("CRITICAL", "DB Connectivity Error: "+de.getMessage());
throw de;
}
catch(Exception e){
log.error("Error: ",e);
performance = StatsProvider.getCassandraStats(joinPoint.getSignature().getName());
if(performance != null){
performance.add(System.currentTimeMillis()-start, true);
}
throw e;
}
}
}
Below is the stack trace:
11126 2016-07-04 17:16:58,448[http-nio-8014-exec-16]ERROR CassPerfInterceptor -Error:
11127
java.lang.NullPointerException
11128 at com.owmessaging.qserv.stats.CassPerfInterceptor.invoke(CassPerfInterceptor.java:31)
11129 at sun.reflect.GeneratedMethodAccessor39.invoke(Unknown Source)
11130 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
11131 at java.lang.reflect.Method.invoke(Method.java:497)
11132 at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:621)
11133 at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:610)
11134 at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:68)
11135 at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:168)
11136 at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
11137 at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
11138 at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208)
11139 at com.sun.proxy.$Proxy79.insertMsgInfo(Unknown Source)
11140 at com.owmessaging.qserv.service.impl.QueueServiceImpl.enqueue(QueueServiceImpl.java:151)
Even if I applied preventive check if (performance != null) still I am getting NPE. Is the above check no thread safe. (But note that this is very rare case I got I NPE out of 7000 request.)