Jetty deployers - Webapp Deploy Management component
—
Directed graph system for modeling deployment states, transitions, and path finding through the deployment lifecycle. The graph system provides the underlying structure for the state machine that controls application deployment workflows.
Basic directed graph implementation providing nodes, edges, and path-finding capabilities for modeling state transitions.
/**
* Basic directed graph implementation
*/
public class Graph {
/** Creates a new empty graph */
public Graph();
/** Adds a node to the graph */
public void addNode(Node node);
/** Removes a node from the graph */
public void removeNode(Node node);
/** Returns all nodes in the graph */
public Set<Node> getNodes();
/** Sets the nodes in the graph */
public void setNodes(Set<Node> nodes);
/** Gets a node by its name */
public Node getNodeByName(String name);
/** Adds an edge to the graph */
public void addEdge(Edge edge);
/** Adds an edge between named nodes */
public void addEdge(String from, String to);
/** Removes an edge from the graph */
public void removeEdge(Edge edge);
/** Removes edge between named nodes */
public void removeEdge(String fromNodeName, String toNodeName);
/** Returns all edges in the graph */
public Set<Edge> getEdges();
/** Sets the edges in the graph */
public void setEdges(Set<Edge> edges);
/** Finds all edges connected to the specified node */
public Set<Edge> findEdges(Node node);
/** Finds all edges originating from the specified node */
public Set<Edge> findEdgesFrom(Node from);
/** Gets path between named nodes using BFS algorithm */
public Route getPath(String nodeNameOrigin, String nodeNameDest);
/** Gets path between nodes using BFS algorithm */
public Route getPath(Node from, Node to);
/** Inserts a new node on an existing edge */
public void insertNode(Edge edge, String nodeName);
/** Inserts a new node on an existing edge */
public void insertNode(Edge edge, Node node);
}Usage Examples:
import org.eclipse.jetty.deploy.graph.*;
// Create a custom deployment graph
Graph deploymentGraph = new Graph();
// Add nodes for deployment states
Node undeployed = new Node("undeployed");
Node deploying = new Node("deploying");
Node deployed = new Node("deployed");
Node starting = new Node("starting");
Node started = new Node("started");
deploymentGraph.addNode(undeployed);
deploymentGraph.addNode(deploying);
deploymentGraph.addNode(deployed);
deploymentGraph.addNode(starting);
deploymentGraph.addNode(started);
// Connect nodes with edges
deploymentGraph.addEdge(undeployed, deploying);
deploymentGraph.addEdge(deploying, deployed);
deploymentGraph.addEdge(deployed, starting);
deploymentGraph.addEdge(starting, started);
// Find path between states
Route deploymentPath = deploymentGraph.getPath("undeployed", "started");
System.out.println("Deployment path: " + deploymentPath);
// Insert intermediate state
Node configuring = new Node("configuring");
Edge deployingToDeployed = new Edge(deploying, deployed);
deploymentGraph.insertNode(deployingToDeployed, configuring);
// Query graph structure
Set<Node> allNodes = deploymentGraph.getNodes();
Set<Edge> allEdges = deploymentGraph.getEdges();
Set<Edge> edgesFromDeployed = deploymentGraph.findEdgesFrom(deployed);Represents a basic graph node with a unique name identifier.
/**
* Represents a basic graph node
*/
public final class Node {
/** Creates a node with the specified name */
public Node(String name);
/** Returns the node name */
public String getName();
/** Returns string representation of the node */
public String toString();
/** Returns hash code for the node */
public int hashCode();
/** Checks equality with another object */
public boolean equals(Object obj);
}Represents a basic graph edge connecting two nodes with directional flow.
/**
* Represents a basic graph edge connecting two nodes
*/
public final class Edge {
/** Creates an edge from one node to another */
public Edge(Node from, Node to);
/** Returns the source node */
public Node getFrom();
/** Returns the destination node */
public Node getTo();
/** Returns string representation of the edge */
public String toString();
/** Returns hash code for the edge */
public int hashCode();
/** Checks equality with another object */
public boolean equals(Object obj);
}Represents a route through the graph as a sequence of edges and nodes, typically the result of path-finding operations.
/**
* Represents a route through the graph as a sequence of edges and nodes
*/
public class Route {
/** Creates a new empty route */
public Route();
/** Adds an edge to the route */
public void add(Edge edge);
/** Creates a copy of this route */
public Route forkRoute();
/** Returns the nodes in the route */
public List<Node> getNodes();
/** Returns the edges in the route */
public List<Edge> getEdges();
/** Gets node at the specified index */
public Node getNode(int index);
/** Returns first node in the route */
public Node firstNode();
/** Returns last node in the route */
public Node lastNode();
/** Returns number of nodes in the route */
public int nodes();
/** Returns number of edges in the route */
public int edges();
/** Returns true if route is empty */
public boolean isEmpty();
/** Returns first edge in the route */
public Edge firstEdge();
/** Returns last edge in the route */
public Edge lastEdge();
/** Gets edge at the specified index */
public Edge getEdge(int index);
/** Returns string representation of the route */
public String toString();
}Usage Examples:
// Working with routes from path finding
Route route = graph.getPath("undeployed", "started");
if (!route.isEmpty()) {
System.out.println("Route from undeployed to started:");
// Iterate through nodes in the route
List<Node> nodes = route.getNodes();
for (int i = 0; i < nodes.size(); i++) {
Node node = route.getNode(i);
System.out.println("Step " + i + ": " + node.getName());
}
// Access route endpoints
Node start = route.firstNode();
Node end = route.lastNode();
System.out.println("Route: " + start.getName() + " -> " + end.getName());
// Work with edges in the route
for (int i = 0; i < route.edges(); i++) {
Edge edge = route.getEdge(i);
System.out.println("Transition: " + edge.getFrom().getName() +
" -> " + edge.getTo().getName());
}
}
// Create and manipulate routes manually
Route customRoute = new Route();
customRoute.add(new Edge(new Node("start"), new Node("middle")));
customRoute.add(new Edge(new Node("middle"), new Node("end")));
// Fork routes for parallel processing
Route originalRoute = graph.getPath("deployed", "started");
Route alternativeRoute = originalRoute.forkRoute();
// Modify alternativeRoute independentlyUtility class for outputting graphs in GraphViz Dot format for visualization and debugging.
/**
* Utility for outputting graphs in GraphViz Dot format
*/
public class GraphOutputDot {
/** Writes graph to DOT file for GraphViz visualization */
public static void write(Graph graph, File outputFile) throws IOException;
}Usage Examples:
import org.eclipse.jetty.deploy.graph.GraphOutputDot;
import java.io.File;
import java.io.IOException;
// Export graph to DOT format for visualization
Graph graph = deploymentManager.getLifeCycle();
File dotFile = new File("deployment-lifecycle.dot");
try {
GraphOutputDot.write(graph, dotFile);
System.out.println("Graph exported to: " + dotFile.getAbsolutePath());
// The generated DOT file can be used with GraphViz tools:
// dot -Tpng deployment-lifecycle.dot -o deployment-lifecycle.png
// dot -Tsvg deployment-lifecycle.dot -o deployment-lifecycle.svg
} catch (IOException e) {
System.err.println("Failed to export graph: " + e.getMessage());
}
// Visualize custom graphs
Graph customGraph = new Graph();
// ... build custom graph structure ...
GraphOutputDot.write(customGraph, new File("custom-states.dot"));// Create a state machine for application deployment
Graph stateMachine = new Graph();
// Define states
Node[] states = {
new Node("undeployed"),
new Node("deploying"),
new Node("deployed"),
new Node("starting"),
new Node("started"),
new Node("stopping"),
new Node("failed")
};
// Add all states to graph
for (Node state : states) {
stateMachine.addNode(state);
}
// Define state transitions
stateMachine.addEdge("undeployed", "deploying");
stateMachine.addEdge("deploying", "deployed");
stateMachine.addEdge("deploying", "failed");
stateMachine.addEdge("deployed", "starting");
stateMachine.addEdge("starting", "started");
stateMachine.addEdge("starting", "failed");
stateMachine.addEdge("started", "stopping");
stateMachine.addEdge("stopping", "deployed");
stateMachine.addEdge("stopping", "failed");
// Any state can transition to failed
for (Node state : states) {
if (!"failed".equals(state.getName())) {
stateMachine.addEdge(state, stateMachine.getNodeByName("failed"));
}
}// Validate that a transition is possible
public boolean canTransition(Graph graph, String fromState, String toState) {
Route route = graph.getPath(fromState, toState);
return route != null && !route.isEmpty();
}
// Get all possible next states
public Set<String> getNextStates(Graph graph, String currentState) {
Node currentNode = graph.getNodeByName(currentState);
Set<Edge> outgoingEdges = graph.findEdgesFrom(currentNode);
return outgoingEdges.stream()
.map(edge -> edge.getTo().getName())
.collect(Collectors.toSet());
}
// Find shortest path between states
public List<String> getTransitionPath(Graph graph, String from, String to) {
Route route = graph.getPath(from, to);
if (route == null || route.isEmpty()) {
return Collections.emptyList();
}
return route.getNodes().stream()
.map(Node::getName)
.collect(Collectors.toList());
}Install with Tessl CLI
npx tessl i tessl/maven-org-eclipse-jetty--jetty-deploy