
Le framework d'intégration de Spring est capable de donner l'état actuel de tous les composants EIP et leurs relations sous la forme d'un graphe JSON. Cela semble très pratique pour étudier et déboguer, mais hélas, aucun des outils Google (dont une ou deux fois seulement ) offre une flexibilité suffisante pour visualiser et analyser un tel graphique. Dans cet article, je montrerai comment résoudre ce problème en important un graphique dans un SGBD graphique Neo4j , où cette flexibilité vient en premier.
(tl;dr)
, :
- JSON URL.
- Cypher- Neo4j Browser, URL.
, , .
, Spring Neo4j Cypher. , – .
JSON?
2 :
spring-integration-http
( spring-integration-webflux
), , Integration Graph Controller.spring-integration-core
Spring Boot Actuator, endpoint integrationgraph ( web).
:
{
"contentDescriptor": {
"providerVersion": "5.2.4.RELEASE",
"providerFormatVersion": 1.1,
"provider": "spring-integration",
"name": "analog"
},
"nodes": [
{
"nodeId": 3,
"componentType": "ExecutorSubscribableChannel",
"name": "brokerChannel"
},
],
"links": [
{
"from": 19,
"to": 8,
"type": "output"
},
]
}
3 :
contentDescriptor
– ; name
( spring.application.name
).nodes
– EIP-, . name
, componentType
nodeId
, , .links
, .. EIP-. from
to
nodeId
. type
, 5: input
, output
, route
, error
, discard
.
( EIP) !
, , , componentType
channel.
Spring Integration.
“”, – “”, : nodes
links
. .
Neo4j, - , , , http://localhost:8080/actuator/integrationgraph ( Spring Boot Actuator). JSON, , .
CORS, . Spring Boot (+Actuator) , :
management:
endpoints:
web:
exposure:
include: '*'
cors:
allowed-origins: '*'
allowed-methods: '*'
( production!)
Spring Integration, . .
Neo4j?
Neo4j, 2 :
Neo4j (, ?)
:
Cypher- APOC
- Neo4j, . Neo4j Sandbox .
Neo4j 4.0.1, , . APOC , 2 Neo4j.
1:
Spring Integration, JSON-, , “ ” : – , – , – . : nodeId
, nodeName
componentType
. org.springframework.integration.graph.IntegrationNode
, ( ).
, Neo4j - :
JSON URL, .
Cypher :
// (1) load JSON from URL:
WITH "http://localhost:8080/actuator/integrationgraph" AS url
CALL apoc.load.json(url) YIELD value
WITH value AS json, value.contentDescriptor AS jsonDescriptor
// (2) descriptor:
MERGE (descriptor:Descriptor {name: jsonDescriptor.name})
ON CREATE SET
descriptor.providerVersion = jsonDescriptor.providerVersion,
descriptor.providerFormatVersion = jsonDescriptor.providerFormatVersion,
descriptor.provider = jsonDescriptor.provider
// (3) nodes:
WITH json, descriptor
UNWIND json.nodes AS jsonNode
MERGE (node:Node {nodeId: jsonNode.nodeId})
ON CREATE SET
node.componentType = jsonNode.componentType,
node.name = jsonNode.name
// (4) links:
WITH json, descriptor, node
UNWIND json.links AS jsonLink
MATCH (a:Node {nodeId: jsonLink.from}), (b:Node {nodeId: jsonLink.to})
MERGE (a)-[link:Link {type: jsonLink.type}]->(b)
// (5) result:
RETURN descriptor, node, link
URLNeo4j Sandbox’, , .. localhost
. JSON- , Ăł.
Cypher, ( ):
- APOC-
apoc.load.json(url)
JSON- json
, – jsonDescriptor
. Descriptor
, jsonDescriptor
.
MERGE
, , . , MERGE
CREATE
.- JSON- (
nodes
) UNWIND
Node
, name
componentType
. - (
links
), Link
MATCH
, . - , : , .
Neo4j Browser JSON-, :

-, : EIP- , , Neo4j Browser, , Cypher-:

“” ( ) , . , .
, :
- , EIP- , , , , ,
serverR...
, , , . - ,
Link
, type
. , Cypher, “ ” . - , , , – , .
, , , …
2:
, : , , . Neo4j Browser ( , ), GraSS (Graph Style Sheet), Neo4j Browser’. , , :style
( ):

. Neo4j Browser , , ( ) Node
. Neo4j Browser, , . “” EIP-: , , .. , , , Cypher- - “ ” . , Cypher “ ” : – , . APOC. apoc.merge.node
, / , :
merge nodes with dynamic labels, with support for setting properties ON CREATE or ON MATCH
: , /, – , . , Cypher- , “” , , channel
. CASE
.
: -, , -, JSON- Cypher MERGE
, APOC – apoc.merge.relationship
:
merge relationship with dynamic type, with support for setting properties ON CREATE or ON MATCH
Neo4j 3.APOC- apoc.merge.(relationship|node)
3.x ( , Neo4j Sandbox 2020) onMatchProps
, .
, - “” , , , , , – , . , , , . , “” . DESCRIBES
- .
, , :
// (1) load JSON from URL:
WITH "http://localhost:8080/actuator/integrationgraph" AS url
CALL apoc.load.json(url) YIELD value
WITH value AS json, value.contentDescriptor AS jsonDesc
// (2) descriptor:
MERGE (descriptor:Descriptor {name: jsonDesc.name})
ON CREATE SET
descriptor.providerVersion = jsonDesc.providerVersion,
descriptor.providerFormatVersion = jsonDesc.providerFormatVersion,
descriptor.provider = jsonDesc.provider,
descriptor.updated = localdatetime()
ON MATCH SET
descriptor.updated = localdatetime()
// (3) nodes:
WITH json, descriptor
UNWIND json.nodes AS jsonNode
CALL apoc.merge.node(
/*labels*/ ['Node',
CASE
WHEN jsonNode.componentType IS NULL THEN "<unknown>"
WHEN toLower(jsonNode.componentType) ENDS WITH "channel" THEN "channel"
WHEN toLower(jsonNode.componentType) ENDS WITH "adapter" THEN "adapter"
WHEN jsonNode.componentType CONTAINS '$' THEN "<other>"
ELSE jsonNode.componentType
END],
/*identProps*/ {nodeId: jsonNode.nodeId, appName: descriptor.name},
/*onCreateProps*/{name: jsonNode.name, componentType: jsonNode.componentType},
/*onMatchProps*/ {}
) YIELD node
MERGE (descriptor)-[:DESCRIBES]->(node)
// (4) links:
WITH json, descriptor, node
UNWIND json.links AS jsonLink
MATCH (a:Node {nodeId: jsonLink.from})<-[:DESCRIBES]-(descriptor)-[:DESCRIBES]->(b:Node {nodeId: jsonLink.to})
CALL apoc.merge.relationship(a, toUpper(jsonLink.type), {}, {}, b, {}) YIELD rel
// (5) result:
RETURN descriptor
URLNeo4j Sandbox’, , .. localhost
. JSON- , Ăł.
, - 5 ( ):
- JSON ;
- / , ;
/ , Node
( - ), :
<unknown>
, (, , , , , UnzipTransformer
);channel
, channel, , ExecutorSubscribableChannel
;adapter
, adapter, , inbound-channel-adapter
;<other>
, $
, ( ) , , ServerConfig$$Lambda$994/0x00000008010fd440
;- , , ,
"componentType": "gateway"
.
componentType
. DESCRIBES
.
- / ,
type
JSON- .
. , , nodeId
. , appName
. - .
, , - . .
Spring Integration, ( 350+ 330+ , . ). Neo4j , , , :

Neo4j , . , Neo4j bin/neo4j-admin
, memrec
, , .
, GraSS- (, ) Neo4j Browser’, :style
.
, MATCH (a) RETURN a
, - . , , , . ( name
):
WITH "analog" AS appName
MATCH (:Descriptor {name: appName})-[:DESCRIBES]->(n:Node)-[l*0..1]-(:Node)
RETURN n, l
, , ( ). , .
:

, . Cypher- (. .4 ), style.grass, componentType
Node
. , . , GraSS- EIP- :
node.Node {
defaultCaption: "<id>";
caption: "{name}";
}
Neo4j Browser – :

. , , Neo4j Browser, . .
, Neo4j Spring Integration. , , , :
32 27 :

37 41 :

57 54 :

350 332 :

, JSON- EIP- Spring Integration. Neo4j . Cypher “ ” , . . , ( ) Cypher-, .
– Neo4j Browser. , ; , . , – . Cypher , . , //, / , , / / , / .. , .
L'article original sur la syntaxe Cypher est ici .