Alfresco: JMX from the command line
JMX is great. Alfresco and JMX is awesome. I’ve written before about configuring Alfresco to use tunneling to connect JMX & debuggers to servers that don’t allow access to the higher numbered ports (or to only a few ports). Let’s add another cool tool. (JMX is an Enterprise only feature of Alfresco.)
The Alfresco wiki covers a few of the clients that are available out there. Let’s add another type to the list: JMX from the command line. There are a couple of options for us to choose from. I am partial to jmxterm from CyclopsGroups.org
Jmxterm is an opensource JMX Client (download). It supports auto completion, history browsing and scripting. In a word: cool.
Let’s jump in…
First thing you need to do with the client is connect
With jmxterm you can pass a connection string via the jar to connect to Alfresco
java -jar jmxterm-1.0-alpha-4-uber.jar -l \ service:jmx:rmi:///jndi/rmi://<host>:50500/alfresco/jmxrmi -p <password> -u <user>
Or, you can connect via the interactive shell
java -jar jmxterm-1.0-alpha-4-uber.jar
Next, using the open
command connect to Alfresco
$>open service:jmx:rmi:///jndi/rmi://localhost:50500/alfresco/jmxrmi -p change_asap -u \ controlRole<br />
#Connection to service:jmx:rmi:///jndi/rmi://localhost:50500/alfresco/jmxrmi is opened
Or, using the jvms
command (with the appropriate user permissions you can list the running java processes on the machine jmxterm is running on).
$>jvms<br />
94822 ( ) - jmxterm-1.0-alpha-4-uber.jar<br />
13157 (m) - org.apache.catalina.startup.Bootstrap start
And once again use the open
command to connect
$>open 13157 -u controlRole -p change_asap<br />
#Connection to 13157 is opened
Now that you are connected let’s perform a simple operation, finding out who is logged into Alfresco and then disconnect one of the users.
First you’ll list the domains that are available
$>domains<br />
#following domains are available<br />
Alfresco<br />
Catalina<br />
JMImplementation<br />
Users<br />
axis<br />
com.sun.management<br />
connector<br />
java.lang<br />
java.util.logging<br />
log4j
The bean you need is in the Alfresco
domain
$>domain Alfresco<br />
#domain is set to Alfresco
You can look up the beans within the domain by using the beans
command. There are quite a few beans in the Alfresco
domain, so let’s connect directly to the one that you need: RepoServerMgmt
. (Don’t forget jmxterm support auto completion.)
$>bean Alfresco:Name=RepoServerMgmt<br />
#bean is set to Alfresco:Name=RepoServerMgmt
Now that you have the bean, you can now find out what it does by using the info
command
$>info<br />
#mbean = Alfresco:Name=RepoServerMgmt<br />
#class name = org.alfresco.repo.admin.RepoServerMgmt<br />
# attributes<br />
%0 - LinkValidationDisabled (boolean, r)<br />
%1 - MaxUsers (int, r)<br />
%2 - ReadOnly (boolean, r)<br />
%3 - TicketCountAll (int, r)<br />
%4 - TicketCountNonExpired (int, r)<br />
%5 - UserCountAll (int, r)<br />
%6 - UserCountNonExpired (int, r)<br />
# operations<br />
%0 - int invalidateTicketsAll()<br />
%1 - int invalidateTicketsExpired()<br />
%2 - void invalidateUser(java.lang.String p1)<br />
%3 - [Ljava.lang.String; listUserNamesAll()<br />
%4 - [Ljava.lang.String; listUserNamesNonExpired()<br />
#there's no notifications
There are lots of things you can do here, you can get attributes, you can set attributes, you can run opertaions.
Looking at the returned attributes you can tell a few things: the datatype of each attribute and if you can change it. In this case none of our attributes can be modified, they are all read only (r). ReadWrite would be signified by rw.
Operations are just like Java functions: they can have a return type and you might be able pass parameters to them.
It can also list notifcations, but there is no mechanism (that I have found yet) in jmxterm to subscribe or unsubscribe to them.
Let’s do some more work:
First let’s see how many users are logged in.
$>get UserCountNonExpired<br />
#mbean = Alfresco:Name=RepoServerMgmt:<br />
UserCountNonExpired = 2;
And now let’s find out who these two users are
$>run listUserNamesNonExpired<br />
#calling operation listUserNamesNonExpired of mbean Alfresco:Name=RepoServerMgmt<br />
#operation returns:<br />
[ System, admin ]
So you have 2 user currently in Alfresco: System and admin
Let’s log out the admin user. (Look back at the list from the info
command.) You can either invalidate all of the authenticated users tickets or we can invalidate named user. Since you just want to remove one user let’s invalidate the admin users session. (The System user is a special account, so you will ignore it.)
$>run invalidateUser admin<br />
#calling operation invalidateUser of mbean Alfresco:Name=RepoServerMgmt<br />
#operation returns:<br />
null
Remember that this operation does not return anything so jmxterm returns null
.
Let’s now check and see if the admin user is still logged in.
$>run listUserNamesNonExpired<br />
#calling operation listUserNamesNonExpired of mbean Alfresco:Name=RepoServerMgmt<br />
#operation returns:<br />
[ System ]
You’ve now run through some basic operations: connecting to Alfresco, listing and selecting the domain, listing and selecting the bean, discovering what the bean can do, getting an attribute, running an operation.
The last things to cover are scripting/non-interactive mode and setting properties.
From time to time you might see the need, to lock Alfresco down by setting it to Read Only mode. The following two commands will help us do this.
First let’s check the current state:
$ echo get -s -b Alfresco:Name=RepoServerMgmt ReadOnly | java -jar jmxterm-1.0-alpha-4-uber.jar -l service:jmx:rmi:///jndi/rmi://localhost:50500/alfresco/jmxrmi -p change_asap -u controlRole -v silent -n
When passing commands to jmxterm, you need to echo the command into the interpreter. So the above command passes the jmxterm get command. we pass it a -s
since we just want the value and not the full expression (ReadOnly = <value>;
) returned -b
names the bean and finally the attribute we are querying. On the jmxterm side we pass the connection information (connection string or PID, username and password), set the verbosity of the execution, and tell it that it should run in non-interactive mode.
In this case the command returns the value false
. So the value of ReadOnly
is false
— Alfresco is in Read/Write mode.
Now let’s put it in ReadOnly mode
$ echo set -b Alfresco:Category=sysAdmin,Type=Configuration,id1=default server.transaction.allow-writes false | java -jar jmxterm-1.0-alpha-4-uber.jar -l service:jmx:rmi:///jndi/rmi://localhost:50500/alfresco/jmxrmi -p change_asap -u controlRole -v silent -n
This follow pretty much the same pattern. The ReadOnly
attribute is a read only property, so to change Alfresco into Read Only mode you set the value of server.transaction.allow-writes
to false
. The set will not return any value. You can then check the current state of the repository by running the previous command and then when you are ready to put the repository back in Read/Write mode change the value of the set command on server.transaction.allow-writes
to true
.