I learned a very valuable lesson the other day when I relied on the Java Editor to recommend the setting of certain members in my classes. This is a silly mistake that occurred and only cost me about 1.5 hours of troubleshooting, but hopefully others can learn from this and not make the same mistake.
WHO TO THANK
I need to thank the following 4 individuals for assisting me with this issue:
1. Serdar Başeğmez – (Who pretty much knew what the issue was but I didn’t understand him properly. Sorry man)
2. Solly Bronkhorst - (My senior Domino Developer at Ukuvuma, who is quite new to Java, but managed to point out the issue fairly quickly. That’s mad skills Solly)
3. Thimo Jansen - (For really trying hard to help me out. I really appreciate the effort Thimo)
4. Paul Withers – (For providing me an alternative to the below issue in Java. Thanks man)
LET ME ADD SOME CONTEXT
In my XPages Applications, my Application Logic is designed around the MVC Architecture. For every Application I usually create a “Global Controller” Java class that initializes certain parts of my application and sets a few members. I access the Global Controller via a managed Bean which I store as a Session Scope Object (Session Scope meaning the Object will remain active for the current Notes Database/Application for the current User only).
Inside this Global Controller, I have a few member properties that get populated on load of the application. (e.g. The current Username, e-mail address, roles, etc). In one of my cases these members needed to be used in my XPages as well as in some of my other Java Classes.
WHAT WAS THE PROBLEM?
While I understood how to get a handle on my Managed Bean via my XPages and Custom Controls, I made an assumption on how to get a handle on it in my other Java Objects. I would import the “Global Controller” into my Java Class and reference its members directly.
Everything worked fine for me when I was testing the application, but the moment there was more than 1 user working in the Application, my Global Controller’s members would be overwritten (i.e the username is not mine, but the 2nd user’s. The same for the roles, e-mail address, etc).
It was as if my Global Controller was being stored as an Application Scope Object and not a Session Scope Object.
WHY DID IT HAPPEN?
When I imported my Global Controller into my other Java Objects and started referencing its member properties, the Java editor started returning errors, telling me that my Global Controller’s members need to be Static. It was here that I allowed the Java Editor to make the necessary changes in my code.
So what does it mean to have a static member? From my understanding, Static members are initialized only once and at the start of the execution. When I launched my XPages Application, my static members would be initialized and would then be stored as values to be used by everyone until they were re-initialized. So if I launched the application first (me as John Jardin), the member properties would be populated with my details, which is correct. If a second user launched the application on her side (Susan Smith), the member properties would be changed and would contain her details. This directly affects me and any user who launched the Application prior to Susan.
You cannot import a Java Object into another Java Object and assume to get a handle on it the same way you would in XPages via a Managed Bean. At least this is how I understand it. What you need to do in your Java Object is get a direct handle to your Managed Bean, which contains an Instance of your Global Controller.
Let’s say that your facesconfig.xml has the following code that defines your Managed Bean:
<managed-bean> <managed-bean-name>GlobalObject</managed-bean-name> <managed-bean-class>com.ukuvuma.designmanager.globals.GlobalObject</managed-bean-class> <managed-bean-scope>session</managed-bean-scope> </managed-bean>
To use this Managed Bean in your Java Object, you’ll need the following code:
FacesContext context = FacesContext.getCurrentInstance(); GlobalObject globals = (GlobalObject) context.getApplication().getVariableResolver().resolveVariable(context,"GlobalObject");
Here you created a variable called “globals” and connected it to your GlobalObject Managed Bean. Now you can continue working with your Global Object in your Java Class. Simple as that.Till next time. Cheers John