Search the FirstSpirit Knowledge Base
Hello everyone, I couldn't find anything about this question in the forum but I'm not sure since I don't speak German.
Please forgive me if it has been already answered.
I have a master project, lets name it "MASTER".
And multiple other projects, lets call one of them "TARGET-1".
I'm trying to create a PageFolder inside an existing folder in the remote project.
I'm programming it in a schedule entry script because I know I'm going to need it more times, but the parent folder and the new folder won't be the same.
This is what I have now:
(Executed in a schedule entry of MASTER project, with its own connection user with admin rights)
AdminService as = context.requireSpecialist(ServicesBroker.TYPE).getService(AdminService.class);
ProjectStorage ps = as.getProjectStorage();
StoreElementAgent storeElementAgent = context.requireSpecialist(StoreElementAgent.TYPE);
for(Project project : ps.getProjects(true)) {
if (project.getName().equals("TARGET-1")) {
context.logInfo(project.getName());
IDProvider parentFolder = storeElementAgent.loadStoreElement("content", PageFolder.UID_TYPE, true);
folder = parentFolder.createPageFolder("NewFolder");
}
}
It works but the folder is created in MASTER.
What I couldn't find is a way of telling "context" that I want to perform in another project.
Is it possible?
Is this a good approach or is there any other process more appropiate for this task?
Thanks,
Andres.
Hi Andres,
the folder is created in the local project because you are using the broker bound to that local project. To work on another project, you have to acquire another broker bound to the target project via a BrokerAgent.
This broker must already be used to retrieve the parent folder you want to create the folder in. As you can directly request that broker based on the project name, there is no need to iterate through the projects. So the following example should replace your complete code:
StoreElementAgent targetProjectAgent = context.requireSpecialist(BrokerAgent.TYPE)
.getBrokerByProjectName("TARGET-1")
.requireSpecialist(StoreElementAgent.TYPE);
if(targetProjectAgent != null) {
IDProvider parentFolder = targetProjectAgent.loadStoreElement("content", PageFolder.UID_TYPE, true);
folder = parentFolder.createPageFolder("NewFolder");
}
Some more hints
The current code will throw a "DuplicateReferenceNameException" if a Page or PageFolder object already exists in the target project (PageFolder and Page share the same UID namespace). Depending on your use case, you should handle this accordingly - e.g. by cancelling the operation, trying to load an already existing folder or by using the createPageFolder method that automatically adds a number in case the desired UID is already in use. In the latter case, you might have to handle the face that the UID of the created folder is different from your "requested" one.
At the moment, you are also not handling the case that the parent folder "content" does not (yet) exist.
As Page and PageFolder objects share the same namespace (and UID_TYPE), it is theoretically possible that you don't get a PageFolder but a Page with the UID "content" if there is one. So you should do an instanceof check here to be safe.
I also strongly recommend to migrate the code from a Beanshell script to a FirstSpirit module later.
Another interesting fact is that it is currently working (in the local project...) even though you are using "true" as the last parameter in the loadStoreElement method which accesses the release store. Usually those elements are write only - you should use "false" here.
As UID, you should better use a name that reflects the common naming scheme for UIDs - in your case "newfolder" or "new_folder" (no capital letters). Although it is "technically possible" to use/set capital letters in UIDs via API, this may lead to problems later especially if you want to change the UID via the UI later (the "change reference name" dialog does not allow to use capital letters).
Hope this helps 🙂
Michael
Hi Andres,
the folder is created in the local project because you are using the broker bound to that local project. To work on another project, you have to acquire another broker bound to the target project via a BrokerAgent.
This broker must already be used to retrieve the parent folder you want to create the folder in. As you can directly request that broker based on the project name, there is no need to iterate through the projects. So the following example should replace your complete code:
StoreElementAgent targetProjectAgent = context.requireSpecialist(BrokerAgent.TYPE)
.getBrokerByProjectName("TARGET-1")
.requireSpecialist(StoreElementAgent.TYPE);
if(targetProjectAgent != null) {
IDProvider parentFolder = targetProjectAgent.loadStoreElement("content", PageFolder.UID_TYPE, true);
folder = parentFolder.createPageFolder("NewFolder");
}
Some more hints
The current code will throw a "DuplicateReferenceNameException" if a Page or PageFolder object already exists in the target project (PageFolder and Page share the same UID namespace). Depending on your use case, you should handle this accordingly - e.g. by cancelling the operation, trying to load an already existing folder or by using the createPageFolder method that automatically adds a number in case the desired UID is already in use. In the latter case, you might have to handle the face that the UID of the created folder is different from your "requested" one.
At the moment, you are also not handling the case that the parent folder "content" does not (yet) exist.
As Page and PageFolder objects share the same namespace (and UID_TYPE), it is theoretically possible that you don't get a PageFolder but a Page with the UID "content" if there is one. So you should do an instanceof check here to be safe.
I also strongly recommend to migrate the code from a Beanshell script to a FirstSpirit module later.
Another interesting fact is that it is currently working (in the local project...) even though you are using "true" as the last parameter in the loadStoreElement method which accesses the release store. Usually those elements are write only - you should use "false" here.
As UID, you should better use a name that reflects the common naming scheme for UIDs - in your case "newfolder" or "new_folder" (no capital letters). Although it is "technically possible" to use/set capital letters in UIDs via API, this may lead to problems later especially if you want to change the UID via the UI later (the "change reference name" dialog does not allow to use capital letters).
Hope this helps 🙂
Michael
Hi mbergmann
Thanks a lot, that method was exactly waht I needed.
However, I struggled with it for a few days because it kept giving me a casting error in the line:
StoreElementAgent targetProjectAgent = context.requireSpecialist(BrokerAgent.TYPE).getBrokerByProjectName("TARGET-1");
It turned out I needed a last method at the en of the chain:
StoreElementAgent targetProjectAgent = context.requireSpecialist(BrokerAgent.TYPE).getBrokerByProjectName("TARGET-1").requireSpecialist(StoreElementAgent.TYPE);
It works as expected now.
Best regards,
Andres.
Hi Andres,
you‘re absolutely right, sorry...
What you get after .getBrokerByProjectName() is of course not the agent yet but the SpecialistsBroker from which to get the agent with another method call.
To avoid confusion, I have edited my previous answer.
Regards,
Michael