
A estrutura do Spring Integration é capaz de fornecer o estado atual de todos os componentes EIP e seus relacionamentos na forma de um gráfico JSON. Parece muito conveniente para estudar e depurar, mas, infelizmente, nenhuma das ferramentas do Google (das quais apenas uma / duas vezes ) oferece flexibilidade suficiente para visualizar e analisar esse gráfico. Neste artigo, mostrarei como resolver esse problema importando um gráfico para um DBMS gráfico do Neo4j , onde essa flexibilidade vem primeiro.
(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 , . , //, / , , / / , / .. , .
O artigo original de destaque da sintaxe Cypher está aqui .