diff --git a/src/data/java/de/tudresden/inf/st/pnml/base/util/ServiceUtils.java b/src/data/java/de/tudresden/inf/st/pnml/base/util/ServiceUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..9079c96d0f3a655bbba0d2cfa94f56f02d43a912
--- /dev/null
+++ b/src/data/java/de/tudresden/inf/st/pnml/base/util/ServiceUtils.java
@@ -0,0 +1,198 @@
+package de.tudresden.inf.st.pnml.base.util;
+
+import de.tudresden.inf.st.pnml.jastadd.model.*;
+
+import java.util.*;
+
+public class ServiceUtils {
+
+    public static Page treeCopyServicePage(PetriNet petriNet, Page servicePrototypePage, int instanceId){
+
+        System.out.println("[ServiceUtils] Copying server page " + servicePrototypePage.getId() + " (" + instanceId + ").");
+        Page copy = treeCopyWithoutArcs(petriNet, servicePrototypePage);
+        updateInstanceIds(copy, "-INSTANCE-" + instanceId);
+        copy.setId(servicePrototypePage.getId() + "-INSTANCE-" + instanceId);
+        copy.getName().setText(copy.getId());
+        reintegrateArcs(servicePrototypePage, copy, "-INSTANCE-" + instanceId);
+        return copy;
+    }
+
+    private static void updateInstanceIds(Page page, String suffix) {
+
+        for (PnObject pnObject : page.getObjects()) {
+            pnObject.setId(pnObject.getId() + suffix);
+
+            if (pnObject.hasName()) {
+                Name name = new Name();
+                name.setText(pnObject.getId());
+                pnObject.setName(name);
+            } else {
+                pnObject.getName().setText(pnObject.getId());
+            }
+
+            if (pnObject.isPageNode()) {
+                updateInstanceIds(pnObject.asPage(), suffix);
+            }
+        }
+    }
+
+    private static void reintegrateArcs(Page original, Page copy, String suffix) {
+
+        Set<Arc> originalArcs = new HashSet<>();
+        getArcsInPage(original, originalArcs);
+
+        for (Arc a : originalArcs) {
+
+            Page originalArcPage = Objects.requireNonNull(getObjectInPage(original, a.getId()))._2;
+            Page arcPage = Objects.requireNonNull(getObjectInPage(copy, originalArcPage.getId() + suffix))._1.asPage();
+            Pair<PnObject, Page> source = getObjectInPage(copy, a.getSource().getId() + suffix);
+            Pair<PnObject, Page> target = getObjectInPage(copy, a.getTarget().getId() + suffix);
+            Arc copyArc = new Arc();
+            assert source != null;
+            copyArc.setSource(source._1.asNode());
+            assert target != null;
+            copyArc.setTarget(target._1.asNode());
+            copyArc.setId(a.getId() + suffix);
+            Name n = new Name();
+            n.setText(a.getId() + suffix);
+            copyArc.setName(n);
+            arcPage.addObject(copyArc);
+        }
+    }
+
+    private static Pair<PnObject, Page> getObjectInPage(Page page, String id) {
+
+        if (page.getId().equals(id)) {
+            return new Pair<>(page, page);
+        }
+
+        for (PnObject o : page.getObjects()) {
+            if (o.getId().equals(id)) {
+                return new Pair<>(o, page);
+            }
+            if (o.isPageNode()) {
+                getObjectInPage(o.asPage(), id);
+            }
+        }
+
+        return null;
+    }
+
+    private static void getArcsInPage(Page page, Set<Arc> arcs) {
+
+        for (PnObject o : page.getObjects()) {
+            if (o.isArcNode()) {
+                arcs.add(o.asArc());
+            }
+            if (o.isPageNode()) {
+                getArcsInPage(o.asPage(), arcs);
+            }
+        }
+    }
+
+    private static Page treeCopyWithoutArcs(PetriNet petriNet, Page currentPage) {
+        return treeCopyWithoutArcsInternal(petriNet, currentPage, null);
+    }
+
+    private static Page treeCopyWithoutArcsInternal(PetriNet petriNet, Page currentPage, Page parent) {
+
+        Map<String, PnObject> rMap = new HashMap<>();
+
+        if (parent == null) {
+            parent = new Page();
+            parent.setId(currentPage.getId());
+            parent.setToolspecificList(currentPage.getToolspecificList().treeCopy());
+            Name n = new Name();
+            n.setText(currentPage.getId());
+            parent.setName(n);
+        }
+
+        for (PnObject pnObject : currentPage.getObjects()) {
+            if (pnObject.isPageNode()) {
+                Page copyPage = new Page();
+                copyPage.setId(pnObject.asPage().getId());
+                copyPage.setToolspecificList(pnObject.asPage().getToolspecificList().treeCopy());
+                copyPage.setName(pnObject.getName().treeCopy());
+                parent.addObject(copyPage);
+
+                treeCopyWithoutArcsInternal(petriNet, pnObject.asPage(), copyPage);
+            }
+
+            if (pnObject.isPlaceObject()) {
+                DinerosPlace copyP = new DinerosPlace();
+                copyP.setId(pnObject.getId());
+                copyP.setName(pnObject.getName().treeCopy());
+
+                if(pnObject.asDinerosPlace().getInitialMarking() == null){
+                    System.out.println("Defaulting initial marking of " + pnObject.getId() + " to 0.");
+
+                    PTMarking defaultMarking = new PTMarking();
+                    defaultMarking.setText(0);
+                    pnObject.asDinerosPlace().setInitialMarking(defaultMarking);
+                } else {
+                    copyP.setInitialMarking(pnObject.asDinerosPlace().getInitialMarking().treeCopy());
+                }
+
+                copyP.setToolspecificList(pnObject.getToolspecificList().treeCopy());
+                parent.addObject(copyP);
+                rMap.put(copyP.getId(), copyP);
+            }
+
+            if (pnObject.isTransitionObject()) {
+                DinerosTransition copyT = new DinerosTransition();
+                copyT.setId(pnObject.getId());
+                copyT.setName(pnObject.getName().treeCopy());
+                copyT.setToolspecificList(pnObject.getToolspecificList().treeCopy());
+                parent.addObject(copyT);
+                rMap.put(copyT.getId(), copyT);
+            }
+        }
+
+        for (PnObject pnObject : currentPage.getObjects()) {
+
+            Name n = new Name();
+            n.setText(pnObject.getId());
+
+            if (pnObject.isRefTransitionObject()) {
+                RefTransition copyRt = new RefTransition();
+                copyRt.setId(pnObject.getId());
+                copyRt.setName(n.treeCopy());
+                copyRt.setRef(Objects.requireNonNull(getReferencedObject(petriNet,
+                        rMap, pnObject.asRefTransitionObject().getRef().getId())).asDinerosTransition());
+                copyRt.setToolspecificList(pnObject.getToolspecificList().treeCopy());
+                parent.addObject(copyRt);
+            }
+
+            if (pnObject.isRefPlaceObject()) {
+                RefPlace copyRp = new RefPlace();
+                copyRp.setId(pnObject.getId());
+                copyRp.setName(n.treeCopy());
+                copyRp.setRef(Objects.requireNonNull(getReferencedObject(petriNet,
+                        rMap, pnObject.asRefPlaceObject().getRef().getId())).asDinerosPlace());
+                copyRp.setToolspecificList(pnObject.getToolspecificList().treeCopy());
+                parent.addObject(copyRp);
+            }
+        }
+
+        return parent;
+    }
+
+    private static PnObject getReferencedObject(PetriNet petriNet,  Map<String, PnObject> rMap, String id){
+
+        PnObject referencedObject = rMap.get(id);
+
+        if(referencedObject == null){
+            System.out.println("Searching for external referenced object: " + id);
+            for(PnObject pnObject : petriNet.allObjects()){
+                if(pnObject.getId().equals(id)){
+                    System.out.println("Found external referenced object: " + id);
+                    return pnObject;
+                }
+            }
+        } else {
+            return referencedObject;
+        }
+
+        return null;
+    }
+}
\ No newline at end of file
diff --git a/src/main/jastadd/base/Navigation.jrag b/src/main/jastadd/base/Navigation.jrag
index d40f4ea9170d12964de6a133efa3411ec212e2b0..e0f7bf38b55394dd3a1ca8a281d698f37ccde2f6 100644
--- a/src/main/jastadd/base/Navigation.jrag
+++ b/src/main/jastadd/base/Navigation.jrag
@@ -96,6 +96,18 @@ aspect Navigation {
   syn boolean PlaceNode.isRefPlace() = false;
   eq RefPlace.isRefPlace() = true;
 
+  syn boolean PnObject.isRefPlaceObject() = false;
+  eq RefPlace.isRefPlaceObject() = true;
+
+  syn RefPlace PnObject.asRefPlaceObject() = null;
+  eq RefPlace.asRefPlaceObject() = this;
+
+  syn boolean PnObject.isRefTransitionObject() = false;
+  eq RefTransition.isRefTransitionObject() = true;
+
+  syn RefTransition PnObject.asRefTransitionObject() = null;
+  eq RefTransition.asRefTransitionObject() = this;
+
   syn Place PlaceNode.asPlace() = null;
   eq Place.asPlace() = this;
 
diff --git a/src/main/jastadd/base/export/PnmlExporter.jadd b/src/main/jastadd/base/export/PnmlExporter.jadd
index 3d8e2aa2c6f0f6ce4e4a44f12433fe306b7d6eb0..6828eb7ad0009a86b620f9ce66568810a43f57e2 100644
--- a/src/main/jastadd/base/export/PnmlExporter.jadd
+++ b/src/main/jastadd/base/export/PnmlExporter.jadd
@@ -146,6 +146,7 @@ aspect PnmlExporter{
         private static Set<RefPlaceHLAPI> convertAndIncludeRefPlaces(PetriNet petriNet, Set<PageHLAPI> convertedPages, Set<PlaceHLAPI> convertedPlaces) {
 
             Set<RefPlaceHLAPI> convertedRefPlaces = new HashSet<>();
+            Set<java.lang.String> convertedRefPlaceIDs = new HashSet<>();
             PlaceHLAPI rootPlace = null;
 
             // get the root transition to construct reference tree
@@ -159,15 +160,19 @@ aspect PnmlExporter{
                             for (RefPlace p_one : petriNet.allRefPlaces()) {
                                 assert rootPlace != null;
                                 if (p_one.getRef().getId().equals(rootPlace.getId())) {
-                                    RefPlaceHLAPI rph = PrimitiveElementsConverter.convertRefPlaceToPnmlObject(p_one, rootPlace, null);
-                                    for (PageHLAPI pageHLAPI : convertedPages) {
-                                        if (pageHLAPI.getId().equals(p_one.ContainingPage().getId())) {
-                                            assert rph != null;
-                                            rph.setContainerPageHLAPI(pageHLAPI);
-                                            break;
+                                    if(!convertedRefPlaceIDs.contains(p_one.getId())) {
+                                        System.out.println("Exporting Ref-Place (l1): " + p_one.getId());
+                                        RefPlaceHLAPI rph = PrimitiveElementsConverter.convertRefPlaceToPnmlObject(p_one, rootPlace, null);
+                                        for (PageHLAPI pageHLAPI : convertedPages) {
+                                            if (pageHLAPI.getId().equals(p_one.ContainingPage().getId())) {
+                                                assert rph != null;
+                                                rph.setContainerPageHLAPI(pageHLAPI);
+                                                break;
+                                            }
                                         }
+                                        convertedRefPlaces.add(rph);
+                                        convertedRefPlaceIDs.add(p_one.getId());
                                     }
-                                    convertedRefPlaces.add(rph);
                                 }
                             }
 
@@ -175,15 +180,19 @@ aspect PnmlExporter{
                             for (RefPlace p_tree : petriNet.allRefPlaces()) {
                                 for (RefPlaceHLAPI convRef : convertedRefPlaces) {
                                     if (convRef.getId().equals(p_tree.getRef().getId())) {
-                                        RefPlaceHLAPI rph = PrimitiveElementsConverter.convertRefPlaceToPnmlObject(p_tree, null, convRef);
-                                        for (PageHLAPI pageHLAPI : convertedPages) {
-                                            if (pageHLAPI.getId().equals(p_tree.ContainingPage().getId())) {
-                                                assert rph != null;
-                                                rph.setContainerPageHLAPI(pageHLAPI);
-                                                break;
+                                        if(!convertedRefPlaceIDs.contains(p_tree.getId())) {
+                                            System.out.println("Exporting Ref-Place (ln): " + p_tree.getId());
+                                            RefPlaceHLAPI rph = PrimitiveElementsConverter.convertRefPlaceToPnmlObject(p_tree, null, convRef);
+                                            for (PageHLAPI pageHLAPI : convertedPages) {
+                                                if (pageHLAPI.getId().equals(p_tree.ContainingPage().getId())) {
+                                                    assert rph != null;
+                                                    rph.setContainerPageHLAPI(pageHLAPI);
+                                                    break;
+                                                }
                                             }
+                                            convertedRefPlaces.add(rph);
+                                            convertedRefPlaceIDs.add(p_tree.getId());
                                         }
-                                        convertedRefPlaces.add(rph);
                                     }
                                 }
                             }
@@ -251,6 +260,7 @@ aspect PnmlExporter{
                 }
 
                 for (PlaceHLAPI ph : convertedPlaces) {
+
                     if (ph.getId().equals(a.getSource().getId())) {
                         source = ph;
                         break;
@@ -301,6 +311,54 @@ aspect PnmlExporter{
                 convertedArcs.add(convertedArc);
             }
 
+            for(ArcHLAPI convertedArc: convertedArcs){
+
+                if(convertedArc.getTarget() == null){
+                    System.out.println("[ERROR] Missing target on arc " + convertedArc.getId());
+                    System.out.println(" >> Searching original of arc " + convertedArc.getId() + " ... ");
+
+                    for(Arc a : petriNet.allArcs()){
+                        if(a.getId().equals(convertedArc.getId())){
+                            System.out.println(" >> Found original arc for " + convertedArc.getId() + " ... ");
+                            System.out.println(" >> Target: " + a.getTarget().getId());
+                            System.out.println(" >> Searching target in places ...");
+                            for (PlaceHLAPI ph : convertedPlaces) {
+                                if(ph.getId().equals(a.getTarget().getId())){
+                                    System.out.println(" >> Found it");
+                                    break;
+                                }
+                            }
+
+                            System.out.println(" >> Searching target in transitions ...");
+                            for (TransitionHLAPI th : convertedTransitions) {
+                                if(th.getId().equals(a.getTarget().getId())){
+                                    System.out.println(" >> Found it");
+                                    break;
+                                }
+                            }
+
+                            System.out.println(" >> Searching target in ref-places ...");
+                            for (RefPlaceHLAPI rth : convertedRefPlaces) {
+                                if(rth.getId().equals(a.getTarget().getId())){
+                                    System.out.println(" >> Found it");
+                                    break;
+                                }
+                            }
+
+                            System.out.println(" >> Searching target in ref-transitions ...");
+                            for (RefTransitionHLAPI tth : convertedRefTransitions) {
+                                if(tth.getId().equals(a.getTarget().getId())){
+                                    System.out.println(" >> Found it");
+                                    break;
+                                }
+                            }
+
+                            break;
+                        }
+                    }
+                }
+            }
+
             return convertedArcs;
         }