Using Selenium with a virtual framebuffer

I needed to run my Selenium tests on a virtual machine, on RedHat Enterprise Linux 6.6 in a multi-screen environment and this messed up the screenshots that the tests took. Virtual frame buffer to the rescue:

First I had to install it,

wget http://vault.centos.org/6.2/os/x86_64/Packages/xorg-x11-server-Xvfb-1.10.4-6.el6.x86_64.rpm

sudo yum localinstall xorg-x11-server-Xvfb-1.10.4-6.el6.x86_64.rpm 

then I could start it,

Xvfb :1 -screen 5 1024x768x8 &

make that terminal session use it,

export DISPLAY=:1.5

and I could finally run my tests, with the screenshots working fine.

Oracle and empty strings

Still as a reminder to myself in case some rows are missing from a query…

Oracle stores empty strings as NULL. So far I’m good, everybody’s aware of that, I think that I know everything. Then suddenly a query doesn’t return all the values I expect from it and I wonder why.

For example if I have the query

SELECT * FROM FOO WHERE BAR <> '';

I may expect it to return every row where BAR isn’t an empty string. Or in Oracle’s case a NULL. Well, too bad, because an empty string isn’t NULL. So any row where BAR is NULL will be ignored and won’t be in the resultset. I have to get rows like that with

SELECT * FROM FOO WHERE BAR IS NOT NULL;

But there is more. Let’s see the next query:

SELECT * FROM FOO WHERE BAR <> 'A';

What does this do? Gets every row where BAR doesn’t equal 'A'? Yes. Except the ones where BAR is NULL. And those rows will miss again.

SELECT * FROM FOO WHERE BAR <> 'A' OR BAR IS NULL;

is the way to go if we really want everything except where BAR is 'A'.

Moral of the story, I should read the documentation before jumping to conclusions, as it clearly states that “If you use any other condition with nulls and the result depends on the value of the null, then the result is UNKNOWN.” and also that “A condition that evaluates to UNKNOWN acts almost like FALSE. For example, a SELECT statement with a condition in the WHERE clause that evaluates to UNKNOWN returns no rows.”

(And of course it behaves the same with UPDATEs and not just with SELECTs.)

Too many beans

Situation: I have a Weblogic container, an application, which I would like to deploy with an ant script and an error message saying:

[wlst] Exception in thread "main" java.lang.IllegalStateException: Traceback (innermost last):
[wlst]   File "/local/bmiklos/projects/.../build/container/weblogic12/weblogic_setup_server.py", line 28, in ?
[wlst]   File "/local/bmiklos/container/weblogic/12.1.1.0.4/server/wlserver/common/wlst/weblogic_base.py", line 328, in createDataSource
[wlst] weblogic.descriptor.BeanAlreadyExistsException: Bean already exists: "weblogic.j2ee.descriptor.wl.JDBCPropertyBeanImpl@8218c7([...]/JDBCDriverParams/Properties/Properties[user])"
[wlst]     at weblogic.descriptor.internal.ReferenceManager.registerBean(ReferenceManager.java:232)
[wlst]     at weblogic.j2ee.descriptor.wl.JDBCPropertiesBeanImpl.setProperties(JDBCPropertiesBeanImpl.java:133)
[wlst]     at weblogic.j2ee.descriptor.wl.JDBCPropertiesBeanImpl.addProperty(JDBCPropertiesBeanImpl.java:79)
[wlst]     at weblogic.j2ee.descriptor.wl.JDBCPropertiesBeanImpl.createProperty(JDBCPropertiesBeanImpl.java:152)
[wlst]     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[wlst]     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
[wlst]     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[wlst]     at java.lang.reflect.Method.invoke(Method.java:601)
[wlst]     at weblogic.management.jmx.modelmbean.WLSModelMBean.invoke(WLSModelMBean.java:437)
[wlst]     at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
[wlst]     at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:792)
[wlst]     at weblogic.management.jmx.mbeanserver.WLSMBeanServerInterceptorBase$16.run(WLSMBeanServerInterceptorBase.java:449)
[wlst]     at java.security.AccessController.doPrivileged(Native Method)
[wlst]     at weblogic.management.jmx.mbeanserver.WLSMBeanServerInterceptorBase.invoke(WLSMBeanServerInterceptorBase.java:447)
[wlst]     at weblogic.management.mbeanservers.internal.JMXContextInterceptor.invoke(JMXContextInterceptor.java:263)
[wlst]     at weblogic.management.jmx.mbeanserver.WLSMBeanServerInterceptorBase$16.run(WLSMBeanServerInterceptorBase.java:449)
[wlst]     at java.security.AccessController.doPrivileged(Native Method)
[wlst]     at weblogic.management.jmx.mbeanserver.WLSMBeanServerInterceptorBase.invoke(WLSMBeanServerInterceptorBase.java:447)
[wlst]     at weblogic.management.mbeanservers.edit.internal.RecordingInterceptor.invoke(RecordingInterceptor.java:199)
[wlst]     at weblogic.management.jmx.mbeanserver.WLSMBeanServerInterceptorBase$16.run(WLSMBeanServerInterceptorBase.java:449)
[wlst]     at java.security.AccessController.doPrivileged(Native Method)
[wlst]     at weblogic.management.jmx.mbeanserver.WLSMBeanServerInterceptorBase.invoke(WLSMBeanServerInterceptorBase.java:447)
[wlst]     at weblogic.management.mbeanservers.internal.SecurityMBeanMgmtOpsInterceptor.invoke(SecurityMBeanMgmtOpsInterceptor.java:65)
[wlst]     at weblogic.management.jmx.mbeanserver.WLSMBeanServerInterceptorBase$16.run(WLSMBeanServerInterceptorBase.java:449)
[wlst]     at java.security.AccessController.doPrivileged(Native Method)
[wlst]     at weblogic.management.jmx.mbeanserverTraceback (innermost last):
[wlst]   File "/local/bmiklos/projects/.../build/container/weblogic12/we.WLSMBeanServerInterceptorBase.invoke(WLSMBeanServerInterceptorBase.java:447)
[wlst]     at weblogic.management.mbeanservers.edit.internal.EditLockInterceptor.invoke(EditLockInterceptor.java:112)
[wlst]     at weblogic.management.jmx.mbeanserver.WLSMBeanServerInterceptorBase$blogic_setup_server.py", line 28, in ?
[wlst]   File "/local/bmiklos/container/weblogic/12.1.1.0.4/server/wlserver/common/wlst/weblogic16.run(WLSMBeanServerInterceptorBase.java:449)
[wlst]     at java.security.AccessController.doPrivileged(Native Method)
[wlst]     at weblogic.manag_base.py", line 328, in createDataSource
[wlst] weblogic.descriptor.BeanAlreadyExistsException: Bean already exists: "weblogic.j2ee.desement.jmx.mbeanserver.WLSMBeanServerInterceptorBase.invoke(WLSMBeanServerInterceptorBase.java:447)
[wlst]     at weblogic.management.mbeancriptor.wl.JDBCPropertyBeanImpl@8218c7([MB-DS]/JDBCDriverParams/Properties/Properties[user])"
[wlst]     at weblogic.descriptor.inteservers.internal.SecurityInterceptor.invoke(SecurityInterceptor.java:444)
[wlst]     at weblogic.management.jmx.mbeanserver.WLSMBeanServerrnal.ReferenceManager.registerBean(ReferenceManager.java:232)
[wlst]     at weblogic.j2ee.descriptor.wl.JDBCPropertiesBeanImpl.setProperti.invoke(WLSMBeanServer.java:323)
[wlst]     at weblogic.management.mbeanservers.internal.JMXConnectorSubjectForwarder$11$1.run(JMXConnectoes(JDBCPropertiesBeanImpl.java:133)
[wlst]     at weblogic.j2ee.descriptor.wl.JDBCPropertiesBeanImpl.addProperty(JDBCPropertiesBeanImpl.jarSubjectForwarder.java:663)
[wlst]     at java.security.AccessController.doPrivileged(Native Method)
[wlst]     at weblogic.management.mbeanservers.va:79)
[wlst]     at weblogic.j2ee.descriptor.wl.JDBCPropertiesBeanImpl.createProperty(JDBCPropertiesBeanImpl.java:152)
[wlst]     at sun.reflect.Nainternal.JMXConnectorSubjectForwarder$11.run(JMXConnectorSubjectForwarder.java:661)
[wlst]     at weblogic.security.acl.internal.AuthentictiveMethodAccessorImpl.invoke0(Native Method)
[wlst]     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
[wlst] atedSubject.doAs(AuthenticatedSubject.java:363)
[wlst]     at weblogic.management.mbeanservers.internal.JMXConnectorSubjectForwarder.invok    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[wlst]     at java.lang.reflect.Method.invoke(Mee(JMXConnectorSubjectForwarder.java:654)
[wlst]     at javax.management.remote.rmi.RMIConnectionImpl.doOperation(RMIConnectionImpl.java:14thod.java:601)
[wlst]     at weblogic.management.jmx.modelmbean.WLSModelMBean.invoke(WLSModelMBean.java:437)
[wlst]     at com.sun.jmx.interceptor.D86)
[wlst]     at javax.management.remote.rmi.RMIConnectionImpl.access$300(RMIConnectionImpl.java:96)
[wlst]     at javax.management.remote.rmi.RMICefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
[wlst]     at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmonnectionImpl$PrivilegedOperation.run(RMIConnectionImpl.java:1327)
[wlst]     at java.security.AccessController.doPrivileged(Native MethodxMBeanServer.java:792)
[wlst]     at weblogic.management.jmx.mbeanserver.WLSMBeanServerInterceptorBase$16.run(WLSMBeanServerInterceptorBas)
[wlst]     at javax.management.remote.rmi.RMIConnectionImpl.doPrivilegedOperation(RMIConnectionImpl.java:1426)
[wlst]     at javax.management.remoe.java:449)
[wlst]     at java.security.AccessController.doPrivileged(Native Method)
[wlst]     at weblogic.management.jmx.mbeanserver.WLSMBeanServete.rmi.RMIConnectionImpl.invoke(RMIConnectionImpl.java:847)
[wlst]     at javax.management.remote.rmi.RMIConnectionImpl_WLSkel.invoke(UnknrInterceptorBase.invoke(WLSMBeanServerInterceptorBase.java:447)
[wlst]     at weblogic.management.mbeanservers.internal.JMXContextIntercepown Source)
[wlst]     at weblogic.rmi.internal.BasicServerRef.invoke(BasicServerRef.java:693)
[wlst]     at weblogic.rmi.internal.BasicServerRef$1.tor.invoke(JMXContextInterceptor.java:263)
[wlst]     at weblogic.management.jmx.mbeanserver.WLSMBeanServerInterceptorBase$16.run(WLSMBeanrun(BasicServerRef.java:518)
[wlst]     at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:363)
[wlst]     at webServerInterceptorBase.java:449)
[wlst]     at java.security.AccessController.doPrivileged(Native Method)
[wlst]     at weblogic.management.jmx.mbeanlogic.security.service.SecurityManager.runAs(SecurityManager.java:146)
[wlst]     at weblogic.rmi.internal.BasicServerRef.handleRequest(Baserver.WLSMBeanServerInterceptorBase.invoke(WLSMBeanServerInterceptorBase.java:447)
[wlst]     at weblogic.management.mbeanservers.edit.insicServerRef.java:514)
[wlst]     at weblogic.rmi.internal.wls.WLSExecuteRequest.run(WLSExecuteRequest.java:118)
[wlst]     at weblogic.work.Executeternal.RecordingInterceptor.invoke(RecordingInterceptor.java:199)
[wlst]     at weblogic.management.jmx.mbeanserver.WLSMBeanServerIntercepThread.execute(ExecuteThread.java:256)
[wlst]     at weblogic.work.ExecuteThread.run(ExecuteThread.java:221)
[wlst]
[wlst] weblogic.descriptor.BeanAlretorBase$16.run(WLSMBeanServerInterceptorBase.java:449)
[wlst]     at java.security.AccessController.doPrivileged(Native Method)
[wlst]     at weblogadyExistsException: weblogic.descriptor.BeanAlreadyExistsException: Bean already exists: "weblogic.j2ee.descriptor.wl.JDBCProperic.management.jmx.mbeanserver.WLSMBeanServerInterceptorBase.invoke(WLSMBeanServerInterceptorBase.java:447)
[wlst]     at weblogic.managemetyBeanImpl@8218c7([MB-DS]/JDBCDriverParams/Properties/Properties[user])"
[wlst]
[wlst]     at weblogic.management.scripting.WLSTInterpretent.mbeanservers.internal.SecurityMBeanMgmtOpsInterceptor.invoke(SecurityMBeanMgmtOpsInterceptor.java:65)
[wlst]     at weblogic.managementrInvoker.printError(WLSTInterpreterInvoker.java:146)
[wlst]     at weblogic.management.scripting.WLSTInterpreterInvoker.executePyScript(WL.jmx.mbeanserver.WLSMBeanServerInterceptorBase$16.run(WLSMBeanServerInterceptorBase.java:449)
[wlst]     at java.security.AccessControllerSTInterpreterInvoker.java:111)
[wlst]     at weblogic.management.scripting.WLSTInterpreterInvoker.main(WLSTInterpreterInvoker.java:30)
[wlst] .doPrivileged(Native Method)
[wlst]     at weblogic.management.jmx.mbeanserver.WLSMBeanServerInterceptorBase.invoke(WLSMBeanServerInterceptorBase.java:447)
[wlst]     at weblogic.management.mbeanservers.edit

The problem in my case is that the container gets corrupt somehow, so I need to delete the directory containing it and re-create the whole thing. After that deploying my application works again.

Velocity template not showing results from Java method call

We can call methods of any Java class from Apache Velocity. Now if that method happens to return a List<String>, and then process that list with #foreach, then we should be aware that in Velocity the result will be something like [foo, bar] instead of ["foo", "bar"]. We will get an array of texts and not an array of strings. If we assume that we get strings and try to manipulate them that way, let’s say by calling toUpperCase() on them Velocity may just decide to ignore that method call on a thing that doesn’t have that method and show nothing as a result. No error messages either. Making it quite hard to figure out what went wrong. At least this happened in my case.

Struts validation variable back referencing

Old Struts 1.x project.  I’m new to Struts and I was trying to validate a string with minlength, and if the length is not enough, then display an error message which contains the original string and the length of the original string. Not because it makes sense, but because that’s what I am asked to do. And I’m trying to do this with the validation XML, because all of the project’s validation stuff is declared in XML files.
Struts has a relatively good documentation, with examples and everything, but they don’t really mention anywhere how their extra stuff, like *this* works. Anyway, *this* was the closest thing that I could find to solve my problem, so I gave it a try. After a few tries my validation XML looked like this:

<field property="input" depends="minlength">
    <arg0 key="search.string" />
    <arg1 name="minlength" key="${var:minlength}" resource="false" />
    <arg2 name="minlength" key="${var:input}" resource="false" />
    <arg3 name="minlength" key="${var:length}" resource="false" />
    <var>
        <var-name>minlength</var-name>
        <var-value>15</var-value>
    </var>
    <var>
        <var-name>input</var-name>
        <var-value>*this*</var-value>
    </var>
    <var>
        <var-name>length</var-name>
        <var-value>(*this*).length()</var-value>
    </var>
</field>

but it doesn’t work, it just put “*this*” and “(*this*).length()” into the error message. (Which is kind of understandable.)
Then I put the question on Stackoverflow, then nobody answered for a long time. And after consulting with a senior developer I came to the conclusion that this most likely can’t be done with a validation XML file. I put this here so if others try to still do something like this in legacy code like this. But there are other ways to validate in Struts too and they are more flexible than the XML.
Just in case anybody has to do anything like this on a legacy project… there you go.

Tablet problems

I got a mini heart attack today.
I got a new tablet somewhat recently. It’s an Ainol Novo 7 Venus. Today as I left work, I checked my e-mails on the tablet, it was working fine. As I got home the screen didn’t turn on, it remained dark. A little googling showed that others have seen the same problem. Which is nice, I only have to hard reset the tablet. The problem is that I couldn’t find it anywhere on the internet how to do that. So in case somebody else is looking for that too (or in the case I forget it):

To reset the Ainol Venus one must press the power and the volume up buttons together and hold them for a few seconds.

May it help to you too!

Setting up PHP CodeSniffer with NetBeans

I’m setting up phpMD / CodeSniffer into my NetBeans 7.3 on Xubuntu 12.10 again, so that I don’t have to look all the stuff up again.

First I install the plugin.

Then it complains that the underlying stuff isn’t properly configured. (Of course it isn’t as I haven’t installed anything else yet.)

Let’s start with Mess Detector, as its webpage suggests.

sudo pear channel-discover pear.phpmd.org
sudo pear remote-list -c phpmd
sudo pear install phpmd/PHP_PMD

Now NetBeans’s options dialog can detect Mess Detector and it says it works fine.
The next one will be CodeSniffer.

sudo pear install PHP_CodeSniffer

And after NetBeans detects it, I set the ‘standard’ field to ‘Zend’ instead of ‘PEAR’.

The only one that remains is Copy Paste Detector. Installing it as its webpage suggests. Note: php-unit should not be installed through apt or it would cause some problems.

sudo pear config-set auto_discover 1
sudo pear install pear.phpunit.de/phpcpd

Setting up my Apache with Zend Framework on Xubuntu 12.10

This is just a slight modification of my other post for achieving the same thing on Debian Wheezy.
I have a fresh install of Xubuntu 12.10. (Since it is based on Ubuntu, this should work just fine with Ubuntu 12.10 as well.) I use the official repositories. I’m configuring it for Zend Framework development. Other tutorials on the web describe all this a little bit differently but I am trying to set up Zend Framework for my own needs, so if this works to you then fine, if not then just look for another tutorial.

First I install Zend Framework itself.

sudo apt-get install zend-framework zend-framework-bin

I’ll also need MySQL support and xdebug.

sudo apt-get install php5-mysql php5-xdebug

Let’s see if Zend works, and create a test project.

zf create project ~/workspace/testproject testproject

It also suggest that I should create my VHOST file. Let’s add the suggested lines to the file:

/etc/apache2/sites-available/testproject

The file needs to be enabled in Apache:

sudo a2ensite testproject

I’ll also need to add the testproject domain to my /etc/hosts file.

Zend will also need mod_rewrite, so I enable it too:

sudo a2enmod rewrite

For xdebug I’ll also need the necessary settings in the php.ini file. I’ll just use the settings from this xdebug tutorial. Except that I didn’t install xdebug through PECL, so I’ll use

zend_extension=/usr/lib/php5/xdebug.so

And then finally I restart Apache.

sudo service apache2 restart

And while on Debian this worked just fine at this point, on Ubuntu I also have to create a symbolic link for the Zend library to use all my projects that I work on:

sudo ln -s /usr/share/php/libzend-framework-php/Zend/ /usr/share/php/Zend

(I don’t know if this is due to the projects’ settings, or a Zend thing, but I’m not interested in finding it out, because changing the project settings could break things on other team members’ computers.)

Debugging ‘No writers were added’ error

Recently I got some

PHP Fatal error: Uncaught exception 'Zend_Log_Exception' with message 'No writers were added'

messages in the Apache error log file. The reason is most of the time (at least in my projects) is that the Zend_Log_Writer_Stream constructor returns null. Just a reminder to myself how to solve the problem:

  1. make sure the path to the file exists
  2. if that didn’t help, make sure the file exists
  3. if that didn’t help, make sure the file is writeable by www-data.
    sudo chown www-data file.log and sudo chmod u+w file.log should do the trick.
  4. if that didn’t help, make sure the file is writeable by others.
    sudo chmod o+w file.log should do the trick.
    (No. This one should not be done. It’s bad practice, insecure, and everything. It can be used only to test that after so many hours of debugging I’m still sane, and file permissions aren’t the issue here. Or to figure out that in this particular case it isn’t www-data who wants to write the file, but some other user, for example because it’s a command line PHP script running as another user.)
  5. if that didn’t help, make sure the file isn’t open anywhere else. In my case the problem was that there was a Zend_Log descendant singleton which held a static copy of the Zend_Log_Writer_Stream which never got closed. (As an irrelevant note, we should do code reviews more often.)

Setting up my Apache with Zend Framework on Debian Wheezy

I have a fresh install of Debian Wheezy. I use the official repositories. I’m configuring it for Zend Framework development. Other tutorials on the web describe all this a little bit differently but I am trying to set up Zend Framework for my own needs, so if this works to you then fine, if not then just look for another tutorial.

First I install Zend Framework itself.

sudo apt-get install zendframework zendframework-bin

I’ll also need MySQL support, and PHPUnit.

sudo apt-get install php5-mysql phpunit

Let’s see if Zend works, and create a test project.

zf create project ~/workspace/testproject testproject

It also suggest that I should create my VHOST file. Let’s add the suggested lines to the file:

/etc/apache2/sites-available/testproject

The file needs to be enabled in Apache:

sudo a2ensite testproject

I’ll also need to add the testproject domain to my /etc/hosts file.

Zend will also need mod_rewrite, so I enable it too:

sudo a2enmod rewrite

I’ll also need xdebug, but it’s already installed so I only need the necessary settings in the php.ini file. I’ll just use the settings from this xdebug tutorial. Except that I didn’t install xdebug through PECL, so I’ll use

zend_extension=/usr/lib/php5/xdebug.so

And then finally I restart Apache.

sudo service apache2 restart