I'm struggling with a validation I would like to implement. I would like to verify that every Methods from a Service that start with update must have the @Transactional annotation. So far I have made a concept that gives me the methods from my service class that start with update (e.g. updateInvoice). But i have no idea how to build a constraint that select the methods wich have no @Transaction annotation.
Asked
Active
Viewed 120 times
2 Answers
3
I'd recommend to define some concepts representing your key elements to define constraints on them, i.e.
Your services:
<concept id="service:ServiceClass">
<description>Adds a label "Service" to every class annotated by "@com.mycompany.services.Service"</description>
<cypher><![CDATA[
MATCH
(service:Type:Class)-[:ANNOTATED_BY]->()-[:OF_TYPE]->(serviceAnnotationType)
SET
service:Service
WHERE
serviceAnnotationType.fqn = "com.mycompany.services.Service"
RETURN
service
]]>
</cypher>
</concept>
Your transacted methods:
<concept id="service:TransactMethod">
<description>Adds a label "Transact" to every method annotated by "@com.mycompany.services.Transact"</description>
<cypher><![CDATA[
MATCH
(method:Method)-[:ANNOTATED_BY]->()-[:OF_TYPE]->(transactAnnotationType)
SET
method:Transact
WHERE
transactAnnotationType.fqn = "com.mycompany.services.Transact"
RETURN
method
]]>
</cypher>
</concept>
Your constraint:
<constraint id="service:AllUpdateMethodsMustBeTransacted">
<requiresConcept refId="service:ServiceClass" />
<requiresConcept refId="service:TransactMethod" />
<description>All update methods must be transacted</description>
<cypher><![CDATA[
MATCH
(service:Service:Class)-[:DECLARES]->(updateMethod:Method)
WHERE
updateMethod.name =~ "update.*" // even this could be extracted to a concept
and not updateMethod:Transact
RETURN
updateMethod
]]>
</cypher>
</constraint >
This approach has several advantages:
- You're getting more rules now but each of them is much better readable (especially the constaint), because you're using terms that you defined for your design
- It's very likely that you will need the concepts "Service" and "Transact" for other constraints too - now just use the labels
- If you're creating a Maven site you get a report about all the concepts in your design (i.e. wich service implementations do currently exist)

Dirk Mahler
- 1,186
- 1
- 6
- 7
-
Thanks, much better than my solution. – rogergl Oct 01 '15 at 07:19
-
Asking these kinds of questions is very valuable feedback. It helps us understand where users run into problems and what needs to be documented, i.e. best practices. – Dirk Mahler Oct 01 '15 at 08:01
-
Sorry - just saw that the concepts were wrong (missing the SET clauses) - fixed it. – Dirk Mahler Oct 01 '15 at 08:04
1
The following seems to work:
match
(aType:Type:Class)-[:ANNOTATED_BY]->()-[:OF_TYPE]->(anAnnotationType:Type),
(aType:Type)-[:DECLARES]->(aMethod:Method)
optional match
(aMethod)-[:ANNOTATED_BY]->()-[:OF_TYPE]->(tType:Type)
with anAnnotationType, aMethod, tType
where
anAnnotationType.fqn = "com.mycompany.services.Service"
and aMethod.name =~ "update.*"
and ((tType is null) or not (tType.fqn = "com.mycompany.services.Transact"))
return
aMethod.name, tType

rogergl
- 3,501
- 2
- 30
- 49