Thursday, 24 March 2011

Trusting self-signed certificates

Yesterday I worked on a task that involved changing user password in Active Directory. Changing users pasword in AD requires secure connection (636 port) and self signed certificate was used (it was a test machine after all). I knew that Java won't accept that certificate, but was surprised that even Luma didn't accept the certificate, hence started looking over google to find a solution. Surprisingly nothing came out. There were tons of materials describing how to create a self signed certificate, but nothing how to accept one. After a couple of hours I remembered that one internal project documentation described the thing i needed. Steps:


  1. openssl s_client -connect ad.example.com:636
  2. Copy the certificate (everything between lines 'begin certificate' and 'end certificate' including both lines)in file (e.g. ad-example-com.cert)
  3. keytool -import -alias ad-example-com -file ad-example-com.cert -keystore ad-example-com.keystore
  4. Add certificate and keystore file to Luma (in server configuration view) and now you should be able connect to AD without problems...

In order to connect to AD using Java and accept SSL connection, use see this blog entry (by Andreas Sterbenz). InstallCert java file attached to his blog post is very easy to use in order to create jssecacerts file which can be copied to $JAVA_HOME/jre/lib/security in order to accept the self signed certificate.

Monday, 14 March 2011

Hibernate and native SQL fetching

Today it took me about 3 hours to find a problem in my code that was caused by HHH-2831. Unfortunately Hibernate documentation is vague regarding 'return-join' elements. By reading comments of bug, i realized that i'm not the only one facing the same problem and in all cases it was intuition of developers which proved to be wrong.

I'll explain briefly the essence of problem. Consider two simple hibernate class mappings and named native SQL query:

  <class name="ObjectA" table="OBJECT_A">
<id column="ID" name="id">
<generator class="native" />
</id>
<property name="title" column="TITLE" type="string" length="255" not-null="true" />
<list name="children" cascade="all-delete-orphan">
<key column="OBJECT_A_ID" not-null="true" />
<list-index column="ORDER_INDEX" base="0" />
<one-to-many class="ObjectB" />
</list>
</class>
<class name="ObjectB" table="OBJECT_B">
<id column="ID" name="id">
<generator class="native" />
</id>
<property name="title" column="TITLE" type="string" length="255" not-null="true" /> </class>
<sql-query name="getAll" read-only="true">
<return alias="a" class="com.example.ObjectA" />
<return-join alias="b" property="a.children" />
select {a.*}, {b.*}
from OBJECT_A a
inner join OBJECT_B b on b.OBJECT_A_ID = b.ID
</sql-query>

Now... what do you expect of when executing something like:

List result = session.getNamedQuery("getAll").list()

I was expecting it to be a list of objects of class ObjectA without any duplicates. Unfortunately this is not the case (like it would've been when using HQL). In fact it returns a list of Object[2] elements and with as many duplicates of ObjectA as it has children. The second object in array is ObjectB (child) object. Hence you must filter the list for duplicate elements:

        List finalResult = new ArrayList();
for (Object[] objs : result) {
ObjectA obj = (ObjectA) objs[0];
if (!finalResult.contains(obj)) {
finalResult.add(obj);
}
}

I wonder what will happen in case of another level... They cannot be filtered if those collections are not inverse, because it would automatically update the list of children (remove them).