Spring Data Neo4j #RelatedToVia error on save() - spring-data-neo4j

I'm getting the following error when I try to save an entity which has a #RelatedToVia attribute:
org.springframework.dao.InvalidDataAccessApiUsageException: Null parameter, startNode=NodeImpl#1, endNode=null, type=DynamicRelationshipType[BPA_PROPOSITION]; nested exception is java.lang.IllegalArgumentException: Null parameter, startNode=NodeImpl#1, endNode=null, type=DynamicRelationshipType[BPA_PROPOSITION]
From the error description above it seems that my RelationshipEntity is missing the end node. However, and this is the worst part of the problem, this is not true because I get this error randomly.
Here is the scenario. I'm creating some really simple tests just to check my class mappings. I manually create the classes necessary for each test case and then I save them. As Spring Data "cascades" the persistence of the entities my only concern is to populate the entity under test with its primitive properties and related entities, save it and then retrieve it back to see if the data is there.
This worked well for my first few classes which do not have #RelatedToVia mappings, but not for the ones which use #RelatedToVia. Here are some excerpts from the code which uses #RelatedToVia.
#NodeEntity
public class BasicProbabilityAssignmentFunction {
#GraphId
private Long id;
#RelatedTo(type = RelTypeConstants.BPA_FRAME, direction = Direction.OUTGOING)
private FrameOfDiscernment frameOfDiscernment;
#RelatedToVia(type = RelTypeConstants.BPA_PROPOSITION, direction = Direction.OUTGOING, elementClass = Belief.class)
private Set<Belief> beliefs;
}
#RelationshipEntity
public class Belief {
#GraphId
private Long id;
#StartNode
private BasicProbabilityAssignmentFunction bpaFunction;
#EndNode
private Proposition proposition;
}
#NodeEntity
public class Proposition {
#GraphId
private Long id;
#RelatedTo(type= RelTypeConstants.PROPOSITION_HYPOTHESIS, direction= Direction.OUTGOING)
private Set<Hypothesis> hypotheses;
#RelatedTo(type = RelTypeConstants.FRAME_PROPOSITION, direction = Direction.INCOMING)
private FrameOfDiscernment frameOfDiscernment;
}
Plus, here is an image of the variables state in debbuging mode just before calling the BasicProbabilityAssignmentFunction repository save. Notice that the Belief entity is fully populated!
And also the code used for test:
//this just creates an instance with its attributes populated
BasicProbabilityAssignmentFunction bpaFunction = BasicMockFactory.createBpaFunction();
//this is where I get the error.
bpaFunction = bpaFunctionRepository.save(bpaFunction);
One further note! I managed to stop getting this error by saving all entities (e.g., Proposition, Hypothesis etc) related to BasicProbabilityAssignmentFunction before saving BasicProbabilityAssignmentFunction itself. Nevertheless, I'm not sure why this solved the problem.
Answering Michael comment: Michael, are you saying that the rel-type should be defined in the Belief class itself (instead of using the type property of the #RelatedToVia annotation) or otherwise I should use template.createRelationshipBetween? I tried to use the #RelationshipEntity type property, but the problem persisted. What worked was saving the relationship #EndNode (Proposition) before the #Startnode (BasicProbabilityAssignmentFunction). By doing this, the Belief relationship is created (saved) without problem when the BasicProbabilityAssignmentFunction is saved.

This problem is already known. Please have a look at the following links:
http://forum.springsource.org/showthread.php?124316-Spring-Data-Neo4j-NullPointerException-with-RelatedToVia
https://jira.springsource.org/browse/DATAGRAPH-216

Related

Acumatica - Problem with data displaying in custom field even though saved to database

I created a custom date field in the opportunity screen. The field shows up just as expected. I enter a date save the record, go out, go back in and the date is no longer there. However, when I query the database, the column is there and there is a data in the column. So, even though the date is being stored in the database it is not displaying it in the screen or when I added that value to the generic inquiry it is also blank. I am not a programmer but it seems like that should’ve been an easy thing to do. I found some references on the web of this type of problem but was hoping there was a more straightforward fix than what those appeared, as they were more programming than I am comfortable at this point.
I found many web pages explaining how to do this seemingly simple thing using the customization tools. Not sure what I'm missing.
I am running fairly recent version of 2019R1.
Any help would be appreciated!
Response from an Acumatica support person.. Evidently they changed some things with 2018R1. See comments/answers below from support. Image of the change I made in the customization tool is also below. After making this change the custom field worked as desired.
After reviewing it into more details, it sounds that it could be related to the new implementation of PXProjection on that DAC.
Unlike ver. 2017 R2, some DAC like the PX.Objects.CR.CROpportunity DAC were implemented as a regular Data Access Class:
[System.SerializableAttribute()]
[PXCacheName(Messages.Opportunity)]
[PXPrimaryGraph(typeof(OpportunityMaint))]
[CREmailContactsView(typeof(Select2<Contact,
LeftJoin<BAccount, On<BAccount.bAccountID, Equal<Contact.bAccountID>>>,
Where2<Where<Optional<CROpportunity.bAccountID>, IsNull, And<Contact.contactID, Equal<Optional<CROpportunity.contactID>>>>,
Or2<Where<Optional<CROpportunity.bAccountID>, IsNotNull, And<Contact.bAccountID, Equal<Optional<CROpportunity.bAccountID>>>>,
Or<Contact.contactType, Equal<ContactTypesAttribute.employee>>>>>))]
[PXEMailSource]//NOTE: for assignment map
public partial class CROpportunity : PX.Data.IBqlTable, IAssign, IPXSelectable
{
...
}
In version 2018 R1(and later) the PX.Objects.CR.CROpportunity DAC is a projection over the PX.Objects.CR.Standalone.CROpportunity and PX.Objects.CR.Standalone.CROpportunityRevision DACs:
[System.SerializableAttribute()]
[PXCacheName(Messages.Opportunity)]
[PXPrimaryGraph(typeof(OpportunityMaint))]
[CREmailContactsView(typeof(Select2<Contact,
LeftJoin<BAccount, On<BAccount.bAccountID, Equal<Contact.bAccountID>>>,
Where2<Where<Optional<CROpportunity.bAccountID>, IsNull, And<Contact.contactID, Equal<Optional<CROpportunity.contactID>>>>,
Or2<Where<Optional<CROpportunity.bAccountID>, IsNotNull, And<Contact.bAccountID, Equal<Optional<CROpportunity.bAccountID>>>>,
Or<Contact.contactType, Equal<ContactTypesAttribute.employee>>>>>))]
[PXEMailSource]//NOTE: for assignment map
[PXProjection(typeof(Select2<Standalone.CROpportunity,
InnerJoin<Standalone.CROpportunityRevision,
On<Standalone.CROpportunityRevision.opportunityID, Equal<Standalone.CROpportunity.opportunityID>,
And<Standalone.CROpportunityRevision.revisionID, Equal<Standalone.CROpportunity.defRevisionID>>>>>), Persistent = true)]
public partial class CROpportunity : IBqlTable, IAssign, IPXSelectable
{
...
}
Because of that change, it's now required to declare 2 extension classes, one for Standalone.CROpportunity (normal DAC) and the CROpportunity (PXProjection).
On the PXProjection DAC Extension, please remind to add BqlField to the correspondent field on the Standalone DAC, Ex.: BqlField = typeof(CROpportunityStandaloneExt.usrTest)
public class CROpportunityExt : PXCacheExtension<PX.Objects.CR.CROpportunity>
{
#region UsrTest
[PXDBDecimal(BqlField = typeof(CROpportunityStandaloneExt.usrTest))]
[PXUIField(DisplayName="Test Field")]
public virtual Decimal? UsrTest { get; set; }
public abstract class usrTest : IBqlField { }
#endregion
}
Please find more information on this article below:
Custom field on CROpportunity doesn't display saved value since upgrading from 6.10 or 2017R2 to 2018R1
change made in customization tool

How are aggregates instantiated to test other aggregates with?

Suppose I have an aggregate that, for some operation, requires the existence of another aggregate. Let's assume I have a car and a garage. There might be a command called ParkInGarage that looks like this:
public class ParkInGarage {
#TargetAggregateIdentifier
public final UUID carId;
public final Garage garage;
//... constructor omitted
}
I've read that to validate the existence of an aggregate, it is good practice to use the loaded aggregate in commands since that already implies its existence (as opposed to passing a garageId).
Now when unit-testing the Car using Axon's fixtures, I can not simply instantiate my Garage by saying new Garage(buildGarageCmd). It will say:
java.lang.IllegalStateException: Cannot request current Scope if none is active
Because no infrastructure was set up.
How would I test such a case, or should I design the aggregate differently?
Abstracted, real-world example
The aggregate root I am working with may have a reference to itself to form a tree-structure of said aggregate root. Let's call it Node.
#Aggregate
public class Node {
private Node parentNode;
}
Upon creation, I can pass an Optional<Node> as parent, or set the parent at a later time using a separate command. Whether the parent should be defined as instance or by ID is part of the question.
public class AttachNodeCmd {
#TargetAggregateIdentifier
public final UUID nodeId;
public final Optional<Node> parentNode;
}
In the command handler, I need to check if attaching the node to given parent would introduce a cycle (the structure is supposed to be a tree, not a common graph).
#CommandHandler
public Node(AttachNodeCmd command) {
if (command.parentNode.isPresent()) {
Node currentNode = command.parentNode.get();
while (currentNode != null) {
if (currentNode.equals(this)) throw new RecursionException();
currentNode = currentNode.parentNode.orElse(null);
}
}
//Accept the command by applying() an Event
}
At some point, the parent needs to be instantiated to perform those checks. This could either be done by supplying the aggregate instance in the command (discouraged), or by supplying a Repository<Node> and the nodeId to the command handler, which is the aggregate itself and also discouraged. Currently I don't see a right way to do this and further down the road a way to test it.
I wouldn't put AR instances in commands. Command schemas should be stable and easy to serialize/reserialize as they are message contracts.
What you could do instead is resolving the dependency in the command handler.
//ParkInGarage command handler
Garage garage = garageRepository.garageOfId(command.garageId);
Car car = carRepository.carOfId(command.carId);
car.parkIn(garage);
I don't know Axon Framework at all, but that should be relatively easy to test now.
I think #plalx is putting you on the right track. Commands are part of your API/Message Contract and exposing the Aggregate in there isn't that great an idea.
Additionally I'd like to note that the AggregateFixtures in Axon are there to test a single Aggregate, not the coordination of operations between Aggregates.
Coordination between aggregates/bounded contexts is typically where you see sagas coming in to play. Now to be honest, I am a bit in doubt whether this use case justifies a Saga, but I could imagine that if the ParkCarInGarageCommand fails because the Garage Aggregate is full (for example), that you need to instruct the Car Aggregate through another command telling it it's a no-go. The Saga set up in Axon might help you with this as you can easily catch (1) the exception from handling the command or (2) handle the event notifying the operation wasn't successful.

Sitecore: Glass Mapper Code First

It is possible to automatically generate Sitecore templates just coding models? I'm using Sitecore 8.0 and I saw Glass Mapper Code First approach but I cant find more information about that.
Not sure why there isn't much info about it, but you can definitely model/code first!. I do it alot using the attribute configuration approach like so:
[SitecoreType(true, "{generated guid}")]
public class ExampleModel
{
[SitecoreField("{generated guid}", SitecoreFieldType.SingleLineText)]
public virtual string Title { get; set; }
}
Now how this works. The SitecoreType 'true' value for the first parameter indicates it may be used for codefirst. There is a GlassCodeFirstDataprovider which has an Initialize method, executed in Sitecore's Initialize pipeline. This method will collect all configurations marked for codefirst and create it in the sql dataprovider. The sections and fields are stored in memory. It also takes inheritance into account (base templates).
I think you first need to uncomment some code in the GlassMapperScCustom class you get when you install the project via Nuget. The PostLoad method contains the few lines that execute the Initialize method of each CodeFirstDataprovider.
var dbs = global::Sitecore.Configuration.Factory.GetDatabases();
foreach (var db in dbs)
{
var provider = db.GetDataProviders().FirstOrDefault(x => x is GlassDataProvider) as GlassDataProvider;
if (provider != null)
{
using (new SecurityDisabler())
{
provider.Initialise(db);
}
}
}
Furthermore I would advise to use code first on development only. You can create packages or serialize the templates as usual and deploy them to other environment so you dont need the dataprovider (and potential risks) there.
You can. But it's not going to be Glass related.
Code first is exactly what Sitecore.PathFinder is looking to achieve. There's not a lot of info publicly available on this yet however.
Get started here: https://github.com/JakobChristensen/Sitecore.Pathfinder

Should instance fields access be synchronized in a Tapestry page or component?

If a page or component class has one instance field which is a non-synchronized object, f.ex. an ArrayList, and the application has code that structurally modifies this field, should the access to this field be synchronized ?
F.ex.:
public class MyPageOrComponent
{
#Persist
private List<String> myList;
void setupRender()
{
if (this.myList == null)
{
this.myList = new ArrayList<>();
}
}
void afterRender(MarkupWriter writer)
{
// Should this be synchronized ?
if (someCondition)
{
this.myList.add(something);
}
else
{
this.myList.remove(something);
}
}
}
I'm asking because I seem to understand that Tapestry creates only one instance of a page or component class and it uses this instance for all the connected clients (but please correct me if this is not true).
In short the answer is no, you don't have to because Tapestry does this for you. Tapestry will transform your pages and classes for you at runtime in such a way that wherever you interact with your fields, they will not actually be working on the instance variable but on a managed variable that is thread safe. The full inner workings are beyond me, but a brief reference to the transformation can be found here.
One warning, don't instantiate your page/component variables at decleration. I have seen some strange behaviour around this. So don't do this:
private List<String> myList = new ArrayList<String>;
Tapestry uses some runtime byte code magic to transform your pages and components. Pages and components are singletons but the properties are transformed so that they are backed by a PerThreadValue. This means that each request gets it's own copy of the value so no synchronization is required.
As suggested by #joostschouten you should never initialize a mutable property in the field declaration. The strange behaviour he discusses is caused beacause this will be shared by all requests (since the initializer is only fired once for the page/component singleton). Mutable fields should instead be initialized in a render method (eg #SetupRender)

After obfuscating a WMI application it is giving error

The problem i am facing is...during the installation of my WMI application (which has obfuscated dlls) below error is shown:
Incorrect usage of [ManagementBind] attribute on a method. 'a' on class 'ak' (ak, Myapp.MyProvider, Version=1.3.0.11, Culture=neutral, PublicKeyToken=213fdfdfdf32dfef) definition. It should be on a static method and there should be one matching parameter for every key defined. "
Please let me know how to resolve this error.
It does not sounds logical to obfuscate everything in your WMI provider. Since the metadata (like the names of methods, parameters and classes) describes how your WMI provider looks at the outside. Do you want the users your WMI provider to have a WMI class named ak? And a WMI method named a? I would rather have a MySomethingProvider with a GetInstances method.
But even if you want your users having to deal with obfuscated names, I think this obfuscation does not go well with how the metadata of a Managed WMI Provider should look.
For example, here the ManagementName attribute points to ID, but I bet that obfuscating it will have given ID another name. That is why they don't match
[ManagementBind]
static public WIN32ServiceHost GetInstance([ManagementName("ID")] int processId)
{
}
[ManagementKey]
public int ID
After obfuscation string in ManagementName is still ID, but now the property ID is called A.
[ManagementBind]
static public WIN32ServiceHost a([ManagementName("ID")] int a)
{
}
[ManagementKey]
public int A
So either don't obfuscate at all or only the parts that are not public or are part of your WMI API.