/ Management  

There is a surprisingly easy JavaUI tool; Say goodbye to tedious tasks with the "Simple Client"...Or not!?

Hi there AppWorks fans,

Welcome to a new installment of AppWorks tips.

Sometimes my deep dives expose unexplored territory of the platform which is old and aged. There is probably a lot more that will not reach the eye of wisdom and is behind secret files, but I’ll keep on grinding till we know it all. This time we explore the “Simple client”; A tool found in the javaui components library of the platform.


Let get right into it…

What did I see on my VM during one of my sessions? Let’s start our journey for this post in this folder: cd /opt/opentext/AppWorksPlatform/defaultInst/components/javaui. In this folder we have a file called javaui.jar; When we open this file with JD-GUI, and open the SimpleClient.class, we can see a clear main(String[] args) {...} method…ready for execution:

javaui_001

Browsing this same class file, I see classes like UIManager, JPanel, and JFrame which reminds me to my good old school days, where we crafted Java tools with “Java Swing UI”!

With this knowledge in mind, it’s time to give it a Java boost with a call like this: java -cp "./javaui.jar" com.eibus.tools.simpleclient.SimpleClient. Hmmm, that gives an error caused by ‘java.lang.NoClassDefFoundError: com/eibus/localization/IStringResource’; So, that’s a missing JAR on that classpath! Let’s find it on our server with this command: sudo grep -l -R --text com/eibus/localization/IStringResource /opt | grep '.jar'. This leads to the JAR file: /opt/opentext/AppWorksPlatform/defaultInst/components/basicutil/basicutil.jar. So, let add it with a relative path: java -cp "./javaui.jar:../basicutil/basicutil.jar" com.eibus.tools.simpleclient.SimpleClient. After execution, we get the next ‘NoClassDefFoundError’! We can continue this till we reached the final JAR file to the classpath, but there is a smarter way:

java -cp "./javaui.jar:../../cordyscp.jar" com.eibus.tools.simpleclient.SimpleClient

Now a UI tries to boot, but we get another recognizable error:

javaui_002

Where did we see this one before?…Yes, in this post! Let’s extend our command with an extra parameter:

java -Djava.library.path=/opt/opentext/AppWorksPlatform/defaultInst/lib/ -cp "./javaui.jar:../../cordyscp.jar" com.eibus.tools.simpleclient.SimpleClient

The -D parameter is part of the JVM and must be placed before the -cp (classpath) parameter!

Hmmmm…Another error (a familiar one too!):

javaui_003

This requires a LD_LIBRARY_PATH variable on our VM! How do I know? Well, that’s just my experience from the last 20 years! So, let’s set it like this:

1
2
export CORDYS_HOME=/opt/opentext/AppWorksPlatform/defaultInst
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$CORDYS_HOME/lib

Another execution of the JAR file finally exposes a good old Swing UI tool:

javaui_004

Time for a coffee break before we continue…☕

Back from that coffee-break, we first dive into the LDAP node where we will find the method GetBasicUserDetails. Select it and ‘Compose’ a new SOAP Request. After this you can send the message and have a view on the received message:

javaui_005

NICEEE!

Now give the SOAP message an update like this:

1
2
3
<GetBasicUserDetails xmlns="http://schemas.cordys.com/1.0/ldap">
<dn>o=appworks_tips,cn=cordys,cn=defaultInst,o=23.1.com</dn>
</GetBasicUserDetails>

Great, we can retrieve the same current ‘sysadmin’ account from my own organization! This is correct as I always add this account as administrator to my organizations! Time to get a list of organizations from that same LDAP 1.0 method set:

1
2
3
<GetOrganizations xmlns="http://schemas.cordys.com/1.0/ldap">
<dn>cn=cordys,cn=defaultInst,o=23.1.com</dn>
</GetOrganizations>

Works as expected! This also is an addition to this post where we tried to get a grip on our organization ID! So, we learned something here…

Now what? Hmmmm…We only see service groups of the ‘system’ space!? What happens when we add a new service group in our own organization space!?

…A_FEW_MOMENTS_LATER… (and a hit on the ‘Refresh’ button!)

javaui_006

Another victory! Now let’s create an entity ‘todo’, expose all CRUD operations of the ‘Web Service’ BB and let it manage via the sg_appserver service group. This would look something like this:

javaui_007

Will this work?…Too bad; I get an error caused by javax.xml.ws.WebServiceException: The solution name specified in the web service request namespace does not exist.. I guess we could expect to have a failure!? Would the gap between entity modelling and this tool be too big? Or is it something else that exceeds my knowledge!? Please, have a comment and join the failure-party! 😞


What else?

This what-else-question is always a good to ask when you’re getting speechless…Let’s go through a list of interesting questions:

What is the difference to ‘Use Anonymous’ or use ‘Set’ in the top left?

From what I experience is that ‘Set’ makes it possible to connect directly to a specific service group and retrieve the method sets under it directly. I’m not 100% sure, but after a deep-dive-remote-debug-session, I can conclude it tries to make a connection to the underlying connection point for a service container. Like for example socket://appworks:29099

javaui_008

Only, I get an error about the address already been in use (by a Java-process in my VM sudo netstat -tulpn | grep 29099)!? Maybe it’s my misunderstanding of the concept, or maybe it’s because the underlying platform is changed? I know in the early versions of the platform there was a separate service called wcpddefaultInst which is currently deprecated and replaced with a direct line to TomEE; Could that be the reason? Comment me if I overlook something here…Maybe the tool is just too old for the current platform usage? FYI: I was able to connect after stopping the corresponding service container, but that still retrieved the same set of service groups as the ‘Use Anonymous’ option!? Please, your comment is welcome at the end of this post…

The ‘netstat’ command gives back a Process Identifier (PID); Have a closer look with this command where you replace {PID} with your number: ps -p {PID} -o pid,vsz=MEMORY -o user,group=GROUP -o comm,args=ARGS

Extra tip: You can remotely debug this tool running it via extra debug parameters:

1
java -Xdebug -Xrunjdwp:server=y,transport=dt_socket,address=*:4000,suspend=n -Djava.library.path=/opt/opentext/AppWorksPlatform/defaultInst/lib/ -cp "./javaui.jar:../../cordyscp.jar" com.eibus.tools.simpleclient.SimpleClient

Once up and running you can connect to it with your IDE and do a remote debug session; Like explained here.

What does ‘No Reply’ do? Well, what do you think…dûh!?

No further comment…I guess! 🙄

Is there any logging?

During startup of the JavaUI tool, I see a warning message passing by ‘No Log4j 2 configuration file found’!? This is a strange message because I did set my CORDYS_HOME environment variable which contains my ‘config’ folder including the ‘Log4j2Configuration.xml’ file. Even after passing this specific property in my java command -Dlog.config.file=/opt/opentext/AppWorksPlatform/defaultInst/config/Log4j2Configuration.xml it still complains about not finding it!? Stranger things are happening here. I guess we need to live with the fact it will use the “internal” logging which we can raise with an extra flag -Dlog4j2.debug=true.

A recap on my Java command so far (make sure to place it all after each other; The “<Enter>'s“ are for readability!):

1
2
3
4
5
6
7
java 
-Xdebug
-Xrunjdwp:server=y,transport=dt_socket,address=*:4000,suspend=n
-Djava.library.path=/opt/opentext/AppWorksPlatform/defaultInst/lib/
-Dlog.config.file=/opt/opentext/AppWorksPlatform/defaultInst/config/Log4j2Configuration.xml
-Dlog4j2.debug=true
-cp "./javaui.jar:../../cordyscp.jar" com.eibus.tools.simpleclient.SimpleClient

During this R&D session, I see a lot of messages like this one: Unable to create socket for {hostname} at port 514. A check for this port number via sudo netstat -tulpn | grep 514 is not giving me any results?
This “Remote Shell information” is the only resource I could find about it!

Some more research (on old stuff) brought me to this command to install related packages: yum -y install rsh rsh-server or dnf install rsh rsh-server. These packages are not available anymore in the default packaging system of RHEL 8, so we use EPEL for this. After following this quick guide, I got a ping on port 514. A restart of the JavaUI tool made it compatible with the port again, but it didn’t change the behavior in the UI itself (from what I experience!). Great lessons learned here about that specific port…I saw it also on my previous Azure images; that’s why I invested the time on solving it!

Number of Messages = 1; So, we can send 1K messages and hang our system?

I just tried 1000 messages which already spins up my laptop blower for a brief time! 10K messages was also fine…I received all of them withing 30 sec.; No pain at all…GREAT!

What about those ‘Rate’ numbers below the ‘Send’ button!?

My expectation was to ‘Reset’ those ‘rate’ values back to the original state, but that’s not the case. A quick code-sniff with JD-GUI tells me that it will only reset the counters on the message numbers received; So, start counting from 0. In that same code-sniff, I see the ‘rate’ values are used for a ‘BusEvent’ object (part of this JavaUI tool) with three calls like this:

1
2
3
BusEvent.logRates[0] = receiveRate;
BusEvent.logRates[1] = sendRate;
BusEvent.logRates[2] = logRate;

The ‘BusEvent’ is just for sending, receiving, and a status call of the request being sent out. Only, I see one if-statement passing by where these values are uses, but they always seem to be TRUE:

1
2
3
4
5
6
7
8
9
10
static {
BusEvent.numEvents = new int[] { 0, 0, 0 };
BusEvent.logRates = new int[] { 1, 1, 1 };
}

// We set those 'logRates' in the UI, but the 'numEvents' are never changed!
// So, the below if-statement is always TRUE where 'type' is in list of: [0, 1, 2]
if (BusEvent.numEvents[type] % BusEvent.logRates[type] == 0) { ... }

// 0 modulo {any_value} always equals 0!!

I know…That last part might have been one step too far for this post, but for me this is just a big puzzle to solve! I just enjoy this stuff and sleep better on it; Bear with me! 😊


Just Q/A section

This tool connects to our platform and can call webservices! During a post on the SDK of the platform we asked ourselves the question of how to create a UI tool with a connection to the platform!? Well, this tool might have the answer!?

I went into the rabbit hole (because the initial GetBasicUserDetails magically returned ‘sysadmin’ data without have me entering any credentials!?), but came out pretty messy with even more questions on things like ‘middleware’, ‘inbound/outbound queue’, ‘CCMU (?) property file’, ‘socket connections on socket://{host}:{port}/‘,…Interesting stuff, but too far out of scope for this post! So, no answer found on this question; I guess they use information from the /config/wcp.properties file as I see also trusted password and other LDAP related settings passing by. Have a look yourself with cat /opt/opentext/AppWorksPlatform/defaultInst/config/wcp.properties | grep -E 'pass|pwd|user'.
Next question!

Can we also run it locally? Well, I tried, but it took me too much of my time to make it fully happen. Let’s rephrase the question to: Do you want to run it locally? The answer to this question for me would be a solid ‘No’; For me, it’s sufficient to have it running from within my server where the tool belongs (in my opinion).

Can we run entity webservices? This is a question already busted; The answer is ‘No’, the tool is just too old to do so. Comment me otherwise…

What about any other authorization? Here I got enthusiastic again because I accidentally crashed into our valuable CMC tool (see comment below!). This tool has a nice com.eibus.tools.admin.ldap.LogonForm object. It eventually calls com.novell.ldap.Connection which still creates a ‘Socket’ connection to my hostname, but this time on default CARS port ‘6366’…Well, that completes the circle for me; I keep it with this information. Enough, is enough!

During all my time on this tool, I also had a search for other methods starting with main( in this JavaUI JAR! Guess what…The excursion is not yet over! Give it a shot on these calls too (a task I leave with you!):

  • java {all_other_settings!} -cp "./javaui.jar:../../cordyscp.jar" com.eibus.tools.simpleclient.ListServices
  • java {all_other_settings!} -cp "./javaui.jar:../../cordyscp.jar" com.eibus.tools.XMLFormatter
  • java {all_other_settings!} -cp "./javaui.jar:../../cordyscp.jar" com.eibus.tools.admin.cmc.CordysManagementConsole
  • java {all_other_settings!} -cp "./javaui.jar:../../cordyscp.jar" com.eibus.tools.admin.cmc.security.TristateCheckBox
  • java {all_other_settings!} -cp "./javaui.jar:../../cordyscp.jar" com.eibus.tools.admin.ldap.RemoteLogon

Ohww man, do we learn great stuff here; Or what!? 😍


It’s a “DONE” from my side where we expose the JavaUI JAR package beyond our intentional thoughts for this post! Great, especially when we learned new things from it; Which is the case from my point of view on the Java-command parameters. Would I recommend using the ‘Simple Client’ on a regular basis? No, I would not; There are better resources to call, but it’s still good to see a little history background of the platform. Have the benefits for this post on your side, and we see each other next week in a new post on AppWorks Tips.

Don’t forget to subscribe to get updates on the activities happening on this site. Have you noticed the quiz where you find out if you are also “The AppWorks guy”?