Your suggestion is not necessary bad. Not sure why this would be messy in code:
Graph<Integer,DefaultEdge> graphWithCycles = ...; //Your graph with cycles
//Compute spanning tree
SpanningTreeAlgorithm<DefaultEdge> sa = new KruskalMinimumSpanningTree<>(graphWithCycles);
SpanningTreeAlgorithm.SpanningTree<DefaultEdge> tree = sa.getSpanningTree();
//Create new graph without cycles induced by the spanning tree
Graph<Integer,DefaultEdge> graphWithoutCycles = ...; //Your graph without cycles, definition depends on graphWithCycles
for(DefaultEdge edge: tree.getEdges())
Graphs.addEdgeWithVertices(graphWithoutCycles, graphWithCycles, edge);
There's various other approaches, e.g. you could also simply run a BreadthFirstSearch on your graph with cycles and create a new graph induced by the BFS tree as you go:
Graph<Integer,DefaultEdge> graphWithCycles = ...; //Your graph with cycles
Graph<Integer,DefaultEdge> graphWithoutCycles = ...; //Your graph without cycles
BreadthFirstIterator bfs = new BreadthFirstIterator(graphWithCycles);
while(bfs.hasNext()){
Integer vertex = bfs.next();
graphWithoutCycles.addVertex(vertex);
DefaultEdge edge = bfs.getSpanningTreeEdge(vertex);
if(edge != null) //Edge is null if the vertex is the root of the BFS tree
graphWithoutCycles.addEdge(bfs.getParent(vertex),vertex,edge);
}