I used Neo4j 3.0.6, neo4j-ogm 2.0.5, Spring boot starter 1.4.1 RELEASE, Lucene 5.5.2
This is my Machine and machineSectionSummary class (I only post the field, actually there are properties and constructors). When I call updateMachineSectionSummary function, after call this function and relaunch the program, I can't call machineRepository.findByName and get the error below. How can I fix this? I already tried to remove the Date, changing the relationship name, but its not working
@NodeEntity
public class Machine {
@GraphId
Long graphId;
String id;
private String name;
private String field;
private Date startDate;
private Date endDate;
@Relationship(type = "HAS_DEPTH_UNIT", direction = "OUTGOING")
private Unit depthUnit;
private Double duration;
@Relationship(type = "HAS_DURATION_UNIT", direction = "OUTGOING")
private Unit durationUnit;
private Double cost;
@Relationship(type = "HAS_CURRENCY", direction = "OUTGOING")
private Currency currency;
private Double exchangeRate;
@Transient
private Boolean maxCost;
}
@NodeEntity
public class MachineSectionSummary {
@GraphId
Long graphId;
String id;
@Relationship(type = "HAS_MACHINE", direction = "OUTGOING")
private Machine machine;
private String sectionGroup;
private String category;
private Double duration;
private Double percentDuration;
private Double cost;
private Double percentCost;
@Relationship(type = "HAS_CURRENCY", direction = "OUTGOING")
private Currency currency;
}
In this function, when I try to findById, its work properly on first Run (after clear database and run the program), but after I stop and re-run the program, it always error.
public void updateMachineSectionSummary(String id) {
Machine currentMachine = findById(id);
if (currentMachine == null) {
return;
}
Engine currentEngine = engineService.findByMachineIdAndName(currentMachine.getId(), "Value");
if (currentEngine == null) {
return;
}
List<LineItem> currentLineItemList = lineItemService.findByEngineIdAndActivityTypeOrderByNoAsc(currentEngine.getId(), "Inside");
List<String> sectionGroupList = new ArrayList<String>();
sectionGroupList.add("Section 1");
sectionGroupList.add("Section 2");
sectionGroupList.add("Section 3");
sectionGroupList.add("Section 4");
for (String sectionGroup : sectionGroupList) {
Double durationTotal = currentLineItemList.stream().filter(d -> d.getSection().getGroup().equalsIgnoreCase(sectionGroup))
.mapToDouble(LineItem::getDuration).sum();
durationTotal = durationTotal / 24;
Double percentDurationTotal = (durationTotal / durationTotal) * 100.0;
MachineSectionSummary currentWSSTotal = machineSectionSummaryService.findByMachineNameAndSectionGroupAndCategory(currentMachine.getName(),
sectionGroup, "Total");
if (currentWSSTotal != null) {
currentWSSTotal.setDuration(durationTotal);
currentWSSTotal.setPercentDuration(percentDurationTotal);
machineSectionSummaryService.save(currentWSSTotal);
}
}
}
This is log error when I run the program (second time)
java.lang.IllegalArgumentException: argument type mismatch
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_66]
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_66]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_66]
at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_66]
at org.neo4j.ogm.entity.io.MethodWriter.write(MethodWriter.java:40) ~[neo4j-ogm-core-2.0.5.jar:na]
at org.neo4j.ogm.entity.io.MethodWriter.write(MethodWriter.java:70) ~[neo4j-ogm-core-2.0.5.jar:na]
at org.neo4j.ogm.context.GraphEntityMapper.writeProperty(GraphEntityMapper.java:234) ~[neo4j-ogm-core-2.0.5.jar:na]
at org.neo4j.ogm.context.GraphEntityMapper.setProperties(GraphEntityMapper.java:186) ~[neo4j-ogm-core-2.0.5.jar:na]
at org.neo4j.ogm.context.GraphEntityMapper.mapNodes(GraphEntityMapper.java:162) ~[neo4j-ogm-core-2.0.5.jar:na]
at org.neo4j.ogm.context.GraphEntityMapper.mapEntities(GraphEntityMapper.java:145) ~[neo4j-ogm-core-2.0.5.jar:na]
at org.neo4j.ogm.context.GraphEntityMapper.map(GraphEntityMapper.java:120) ~[neo4j-ogm-core-2.0.5.jar:na]
at org.neo4j.ogm.context.GraphRowListModelMapper.map(GraphRowListModelMapper.java:56) ~[neo4j-ogm-core-2.0.5.jar:na]
at org.neo4j.ogm.session.delegates.LoadByTypeDelegate.loadAll(LoadByTypeDelegate.java:94) ~[neo4j-ogm-core-2.0.5.jar:na]
at org.neo4j.ogm.session.delegates.LoadByTypeDelegate.loadAll(LoadByTypeDelegate.java:157) ~[neo4j-ogm-core-2.0.5.jar:na]
at org.neo4j.ogm.session.Neo4jSession.loadAll(Neo4jSession.java:226) ~[neo4j-ogm-core-2.0.5.jar:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_66]
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_66]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_66]
at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_66]
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:333) ~[spring-aop-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190) ~[spring-aop-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) ~[spring-aop-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:133) ~[spring-aop-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:121) ~[spring-aop-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213) ~[spring-aop-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at com.sun.proxy.$Proxy77.loadAll(Unknown Source) ~[na:na]
at org.springframework.data.neo4j.repository.query.derived.DerivedGraphRepositoryQuery.execute(DerivedGraphRepositoryQuery.java:65) ~[spring-data-neo4j-4.1.3.RELEASE.jar:na]
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:482) ~[spring-data-commons-1.12.3.RELEASE.jar:na]
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:460) ~[spring-data-commons-1.12.3.RELEASE.jar:na]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:61) ~[spring-data-commons-1.12.3.RELEASE.jar:na]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99) ~[spring-tx-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281) ~[spring-tx-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) ~[spring-tx-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136) ~[spring-tx-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) ~[spring-aop-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213) ~[spring-aop-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at com.sun.proxy.$Proxy116.findByName(Unknown Source) ~[na:na]
at com.test.wp.service.MachineServiceImpl.findByName(MachineServiceImpl.java:58) ~[classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_66]
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_66]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_66]
at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_66]
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:333) ~[spring-aop-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190) ~[spring-aop-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) ~[spring-aop-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99) ~[spring-tx-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281) ~[spring-tx-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) ~[spring-tx-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213) ~[spring-aop-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at com.sun.proxy.$Proxy121.findByName(Unknown Source) ~[na:na]
at com.test.wp.service.InitializationServiceImpl.initGlobalOffsetMachines(InitializationServiceImpl.java:998) ~[classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_66]
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_66]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_66]
at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_66]
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:333) ~[spring-aop-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at..
UPDATE
I create sampleProject at Github. Hope this sample helpful. Thank you
There are two parts to this: the first concerns your code and the second is what the OGM should do when it encounters this scenario.
MachineSectionSummary
has a field calledDouble percentDuration
. When you initialise your database it sets every instance to0.0
. The first time you run/initMachineSectionSummary
it callsupdateMachineSectionSummary()
The line that introduces the issue is here:
Double percentDurationTotal = (durationTotal / durationTotal) * 100.0;
. The expression that createsdurationTotal
always returns0.0
. This calculation will result in aNaN
which we then set onMachineSectionSummary.percentDuration
. The OGM then saves this value to Neo4j. The problem occurs as you have found out when you try to retrieve theNaN
value from the database and map it back to aMachineSectionSummary
. The OGM at this point is expecting a Double but gets a String called "NaN" instead and it blows up with the exception:java.lang.IllegalArgumentException: argument type mismatch
.Having worked on a lot of numerical projects in the past my recommendation would be to prevent
NaN
from appearing; that is do some defensive coding where it could potentially originate. That should fix your primary issue.This introduces the second issue: what do we expect the OGM to do here? In some cases some users may want to store
NaN
in the database. Some users may want to make sureNaN
's are alwaysnull
. Either way the OGM should probably alert developers with a better error message.