Wednesday, May 12, 2010

Support for NTLMv2 with Apache HttpClient using JCIFS

Here, I'll explain how to get NTLMv2 support in HttpClient 3.x using JCIFS by using 1 addditional class and inserting 1 new line into your existing calls to HttpClient.
Of course you can use JCIFS NTLM authentication directly in Java even if you don't have Apache HttpClient - I'm not looking at that but you can refer to this guide on JCIFS home page.

HttpClient
Apache's HttpClient provides some useful encapsulation for fetching/posting data over HTTP through Java code. The common version is HttpClient 3.x whereas the latest version is HttpClient 4.x.

NTLM
One of HttpClient's advantages is that it has built in support to manage communications over an NTLM proxy.
NTLM is a very closely guarded Proxy protocol used by Microsoft but still popularly used.

JCIFS
Unfortunately, HttpClient does not have built in support for NTLM v2. The good news is, it allows you to integrate NTLMv2 support through another library called JCIFS.
JCIFS is an Open Source  client library that implements the CIFS/SMB networking protocol in 100% Java. See more details/download from here. But since JCIFS started NTLMv2 support only from 1.3.0, make sure you have the latest JCIFS jar (I tested with JCIFS 1.3.14).

JCIFS in HttpClient
Thankfully, HttpClient 4.x home site has a page containing unofficial steps for integrating JCIFS into HTTPClient. However, these steps will only work for 4.x and not for for 3.x. This is because HttpClient 4.x is not backward compatible with 3.x. There are major changes like package structures, new Engines instead of States, etc.

Since I was using HttpClient 3.x, I started thinking of upgrading to 4.x – but it was obvious upgrading to 4.x from 3.x was a nightmare just to get NTLMv2 support.

Thankfully, it was just a matter of understanding HttpClient 3.x internal calls from the source. I was able to create 1 simple class that will do the integration in 1 smooth move.

Steps and source-code
1)      I created a new class, JCIFS_NTLMScheme.java that would be used in place of HTTPClient's NTLMScheme.
This new class simply makes calls to JCIFS internally to generate NTLMv2's Type1, 2 and 3 messages- just reimplemented the methods with slight logic changes to generate the messages:
package org.xyz;

import java.io.IOException;

import org.apache.commons.httpclient.Credentials;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.NTCredentials;
import org.apache.commons.httpclient.auth.AuthChallengeParser;
import org.apache.commons.httpclient.auth.AuthScheme;
import org.apache.commons.httpclient.auth.AuthenticationException;
import org.apache.commons.httpclient.auth.InvalidCredentialsException;
import org.apache.commons.httpclient.auth.MalformedChallengeException;
import org.sac.crosspather.common.util.AppLogger;
import org.sac.crosspather.common.util.HTTPHelper;

/**
 * This is a reimplementation of HTTPClient 3.x's
 * org.apache.commons.httpclient.auth.NTLMScheme.<BR/>
 * It will basically use JCIFS (v1.3.15) in order to provide added support for
 * NTLMv2 (instead of trying to create its own Type, 2 and 3 messages). <BR/>
 * This class has to be registered manually with HTTPClient before setting
 * NTCredentials: AuthPolicy.registerAuthScheme(AuthPolicy.NTLM,
 * JCIFS_NTLMScheme.class); <BR/>
 * Will <B>not</B> work with HttpClient 4.x which requires AuthEngine to be overriden instead of AuthScheme.
 *
 * @author Sachin M
 */
public class JCIFS_NTLMScheme implements AuthScheme {

       private static AppLogger logger = new AppLogger(HTTPHelper.class.getName());

       /** NTLM challenge string. */
       private String ntlmchallenge = null;

       private static final int UNINITIATED = 0;
       private static final int INITIATED = 1;
       private static final int TYPE1_MSG_GENERATED = 2;
       private static final int TYPE2_MSG_RECEIVED = 3;
       private static final int TYPE3_MSG_GENERATED = 4;
       private static final int FAILED = Integer.MAX_VALUE;

       /** Authentication process state */
       private int state;

       public JCIFS_NTLMScheme() throws AuthenticationException {
              // Check if JCIFS is present. If not present, do not proceed.
              try {
                     Class.forName("jcifs.ntlmssp.NtlmMessage",false,this.getClass().getClassLoader());
              } catch (ClassNotFoundException e) {
                     throw new AuthenticationException("Unable to proceed as JCIFS library is not found.");
              }
       }
      
       public String authenticate(Credentials credentials, HttpMethod method)
                     throws AuthenticationException {
              logger.doLog(AppLogger.FINEST,
                           "Enter JCIFS_NTLMScheme.authenticate(Credentials, HttpMethod)",
                           null);

              if (this.state == UNINITIATED) {
                     throw new IllegalStateException(
                                  "NTLM authentication process has not been initiated");
              }

              NTCredentials ntcredentials = null;
              try {
                     ntcredentials = (NTCredentials) credentials;
              } catch (ClassCastException e) {
                     throw new InvalidCredentialsException(
                                  "Credentials cannot be used for NTLM authentication: "
                                                + credentials.getClass().getName());
              }
             
              NTLM ntlm = new NTLM();
              ntlm.setCredentialCharset(method.getParams().getCredentialCharset());
              String response = null;
              if (this.state == INITIATED || this.state == FAILED) {
                     response = ntlm.generateType1Msg(ntcredentials.getHost(),
                                  ntcredentials.getDomain());
                     this.state = TYPE1_MSG_GENERATED;
              } else {
                     response = ntlm.generateType3Msg(ntcredentials.getUserName(),
                                  ntcredentials.getPassword(), ntcredentials.getHost(),
                                  ntcredentials.getDomain(), this.ntlmchallenge);
                     this.state = TYPE3_MSG_GENERATED;
              }
              return "NTLM " + response;

       }

       public String authenticate(Credentials credentials, String method,
                     String uri) throws AuthenticationException {
              throw new RuntimeException(
                           "Not implemented as it is deprecated anyway in Httpclient 3.x");
       }

       public String getID() {
              throw new RuntimeException(
                           "Not implemented as it is deprecated anyway in Httpclient 3.x");
       }

       /**
        * Returns the authentication parameter with the given name, if available.
        *
        * <p>
        * There are no valid parameters for NTLM authentication so this method
        * always returns <tt>null</tt>.
        * </p>
        *
        * @param name
        *            The name of the parameter to be returned
        *
        * @return the parameter with the given name
        */
       public String getParameter(String name) {
              if (name == null) {
                     throw new IllegalArgumentException("Parameter name may not be null");
              }
              return null;
       }

       /**
        * The concept of an authentication realm is not supported by the NTLM
        * authentication scheme. Always returns <code>null</code>.
        *
        * @return <code>null</code>
        */
       public String getRealm() {
              return null;
       }

       /**
        * Returns textual designation of the NTLM authentication scheme.
        *
        * @return <code>ntlm</code>
        */
       public String getSchemeName() {
              return "ntlm";
       }

       /**
        * Tests if the NTLM authentication process has been completed.
        *
        * @return <tt>true</tt> if Basic authorization has been processed,
        *         <tt>false</tt> otherwise.
        *
        * @since 3.0
        */
       public boolean isComplete() {
              return this.state == TYPE3_MSG_GENERATED || this.state == FAILED;
       }

       /**
        * Returns <tt>true</tt>. NTLM authentication scheme is connection based.
        *
        * @return <tt>true</tt>.
        *
        * @since 3.0
        */
       public boolean isConnectionBased() {
              return true;
       }

       /**
        * Processes the NTLM challenge.
        *
        * @param challenge
        *            the challenge string
        *
        * @throws MalformedChallengeException
        *             is thrown if the authentication challenge is malformed
        *
        * @since 3.0
        */
       public void processChallenge(final String challenge)
                     throws MalformedChallengeException {
              String s = AuthChallengeParser.extractScheme(challenge);
              if (!s.equalsIgnoreCase(getSchemeName())) {
                     throw new MalformedChallengeException("Invalid NTLM challenge: "
                                  + challenge);
              }
              int i = challenge.indexOf(' ');
              if (i != -1) {
                     s = challenge.substring(i, challenge.length());
                     this.ntlmchallenge = s.trim();
                     this.state = TYPE2_MSG_RECEIVED;
              } else {
                     this.ntlmchallenge = "";
                     if (this.state == UNINITIATED) {
                           this.state = INITIATED;
                     } else {
                           this.state = FAILED;
                     }
              }
       }

       private class NTLM {
           /** Character encoding */
           public static final String DEFAULT_CHARSET = "ASCII";
          
           /**
               * The character was used by 3.x's NTLM to encode the username and
               * password. Apparently, this is not needed in when passing username,
               * password from NTCredentials to the JCIFS library
               */
           private String credentialCharset = DEFAULT_CHARSET;
          
              void setCredentialCharset(String credentialCharset) {
                     this.credentialCharset = credentialCharset;
              }

              private String generateType1Msg(String host, String domain) {
                     jcifs.ntlmssp.Type1Message t1m = new jcifs.ntlmssp.Type1Message(jcifs.ntlmssp.Type1Message.getDefaultFlags(),
                                  domain, host);
                     return jcifs.util.Base64.encode(t1m.toByteArray());
              }

              private String generateType3Msg(String username, String password, String host,
                           String domain, String challenge) {
                     jcifs.ntlmssp.Type2Message t2m;
                     try {
                           t2m = new jcifs.ntlmssp.Type2Message(jcifs.util.Base64.decode(challenge));
                     } catch (IOException e) {
                           throw new RuntimeException("Invalid Type2 message", e);
                     }

                     jcifs.ntlmssp.Type3Message t3m = new jcifs.ntlmssp.Type3Message(t2m, password, domain,
                                  username, host, 0);
                     return jcifs.util.Base64.encode(t3m.toByteArray());
              }
       }
}

2)      Then it was Register the new JCIFS_NTLMScheme class as the replacement for NTLMScheme by using the following command:
AuthPolicy.registerAuthScheme(AuthPolicy.NTLM, org.xyz.JCIFS_NTLMScheme.class);
 (AuthPolicy is a class in HTTPClient 3.x jar)

That's it! Use your HTTPClient as normal but just make sure you call the above register command before you create and bind the HttpClient's NTCredentials class

Thursday, October 22, 2009

Best Software Utilities (Non-IT) List

Here's a list of my favourite, eternally useful list of extremely useful Software Utilities / Tools.

It will be a Forever Updated post, with new additions regularly for Windows - obviously with a slight preference to Java + Open-source versions if competing apps are similar.
For Best Developer Utilities, see this earlier post, Must have tools for the Smart Java Professional.

If an app replaces an existing one, or if there are close seconds, the losing app will move to the Best Software Utilities (non-IT) Honour List.

Find out whats eating your Hard Disk space
WinDirStat: Gives a very unique visual categorization of which files and folders contain what. OpenSource, Windows
FolderSize: A quick way to analyse your usage but without advanced features. Freeware, Windows
JDiskReport: A Java-based disk analyser. Freeware, Java

Recover Lost Files
NTFS Undelete: Free software ported from the open-source Unix version of ntfs undelete utility. EXCELLENT! OpenSource, Windows

Watch any video format without installing codecs
VLC media player: Free all-in-one media player that plays every video format out there without additional codecs OpenSource, Windows

Tuesday, July 14, 2009

Error in Tolven RC1 configPhase3 - ORA-00932

Running configPhase3.bat of Tolven RC1 (with Windows-OpenLdap/Oracle10g/Jboss) was causing errors.

The command prompt showed:
C:\tolven\tolven-RC1\bin>configPhase3.bat
0 [main] INFO root - Start log4j - Configuration: file:/C:/tolven/tolven-RC1/bi
n/tolven-log4j.xml, logFileName: C:\tolven\tolven-RC1\log\tolven.log
18:29:07,570 INFO [TPFBoot] Loaded configDir C:\tolven\tolven-config
18:29:07,695 INFO [TPFBoot] Generated boot.properties: C:\DOCUME~1\sachin\LOC
ALS~1\Temp\tpf_7376485784350116145_boot.properties
18:29:07,757 INFO [TolvenApplicationInitializer] logging system initialized
18:29:07,757 INFO [TolvenApplicationInitializer] application root is C:\tolven\
tolven-RC1\bin
18:29:08,023 INFO [PluginRegistryImpl] configured, stopOnError=true, isValidati
ng=false
18:29:08,132 INFO [ShadingPathResolver] configured, shadow folder is C:\tolven\
tolven-config\build\temp\.jpf-shadow
18:29:08,757 INFO [PluginRegistryImpl] plug-in and fragment descriptors registe
red - 117
18:29:08,804 WARN [ShadingPathResolver] old context URL file:/C:/tolven/tolven-
config/repositoryRuntime/plugins/org.tolven.library.jasperreports-0.0.1.zip has
been replaced with new file:/C:/tolven/tolven-config/repositoryRuntime/plugins/o
rg.tolven.library.jasperreports-0.0.1.zip for {PluginFragment: uid=org.tolven.li
brary.jasperreports@0.0.1} with key org.tolven.library.jasperreports
18:29:08,804 WARN [ShadingPathResolver] old context URL file:/C:/tolven/tolven-
config/repositoryRuntime/plugins/org.tolven.assembler.jboss.oracle-0.0.1.zip has
been replaced with new file:/C:/tolven/tolven-config/repositoryRuntime/plugins/
org.tolven.assembler.jboss.oracle-0.0.1.zip for {PluginFragment: uid=org.tolven.
assembler.jboss.oracle@0.0.1} with key org.tolven.assembler.jboss.oracle
18:29:08,804 WARN [ShadingPathResolver] old context URL file:/C:/tolven/tolven-
config/repositoryRuntime/plugins/org.tolven.library.jboss-0.0.1.zip has been rep
laced with new file:/C:/tolven/tolven-config/repositoryRuntime/plugins/org.tolve
n.library.jboss-0.0.1.zip for {PluginFragment: uid=org.tolven.library.jboss@0.0.
1} with key org.tolven.library.jboss
18:29:08,804 WARN [ShadingPathResolver] old context URL file:/C:/tolven/tolven-
config/repositoryRuntime/plugins/org.tolven.assembler.jboss-0.0.2.zip has been r
eplaced with new file:/C:/tolven/tolven-config/repositoryRuntime/plugins/org.tol
ven.assembler.jboss-0.0.2.zip for {PluginFragment: uid=org.tolven.assembler.jbos
s@0.0.1} with key org.tolven.assembler.jboss
18:29:08,820 WARN [ShadingPathResolver] old context URL file:/C:/tolven/tolven-
config/repositoryRuntime/plugins/org.tolven.deploy.source-0.0.2.zip has been rep
laced with new file:/C:/tolven/tolven-config/repositoryRuntime/plugins/org.tolve
n.deploy.source-0.0.2.zip for {PluginFragment: uid=org.tolven.deploy.source@0.0.
1} with key org.tolven.deploy.source
18:29:08,820 WARN [ShadingPathResolver] old context URL file:/C:/tolven/tolven-
config/repositoryRuntime/plugins/org.tolven.assembler.oracle.persistencexml-0.0.
1.zip has been replaced with new file:/C:/tolven/tolven-config/repositoryRuntime
/plugins/org.tolven.assembler.oracle.persistencexml-0.0.1.zip for {PluginFragmen
t: uid=org.tolven.assembler.oracle.persistencexml@0.0.1} with key org.tolven.ass
embler.oracle.persistencexml
18:29:08,820 WARN [ShadingPathResolver] old context URL file:/C:/tolven/tolven-
config/repositoryRuntime/plugins/org.tolven.component.oracle.init-0.0.1.zip has
been replaced with new file:/C:/tolven/tolven-config/repositoryRuntime/plugins/o
rg.tolven.component.oracle.init-0.0.1.zip for {PluginFragment: uid=org.tolven.co
mponent.oracle.init@0.0.1} with key org.tolven.component.oracle.init
18:29:08,820 WARN [ShadingPathResolver] old context URL file:/C:/tolven/tolven-
config/repositoryRuntime/plugins/org.tolven.deploy.jboss-0.0.3.zip has been repl
aced with new file:/C:/tolven/tolven-config/repositoryRuntime/plugins/org.tolven
.deploy.jboss-0.0.3.zip for {PluginFragment: uid=org.tolven.deploy.jboss@0.0.1}
with key org.tolven.deploy.jboss
18:29:08,820 WARN [ShadingPathResolver] old context URL file:/C:/tolven/tolven-
config/repositoryRuntime/plugins/org.tolven.component.application.oracle.indexes
-0.0.1.zip has been replaced with new file:/C:/tolven/tolven-config/repositoryRu
ntime/plugins/org.tolven.component.application.oracle.indexes-0.0.1.zip for {Plu
ginFragment: uid=org.tolven.component.application.oracle.indexes@0.0.1} with key
org.tolven.component.application.oracle.indexes
18:29:08,820 WARN [ShadingPathResolver] old context URL file:/C:/tolven/tolven-
config/repositoryRuntime/plugins/org.tolven.assembler.oracle.orm-0.0.1.zip has b
een replaced with new file:/C:/tolven/tolven-config/repositoryRuntime/plugins/or
g.tolven.assembler.oracle.orm-0.0.1.zip for {PluginFragment: uid=org.tolven.asse
mbler.oracle.orm@0.0.1} with key org.tolven.assembler.oracle.orm
18:29:08,820 WARN [ShadingPathResolver] old context URL file:/C:/tolven/tolven-
config/repositoryRuntime/plugins/org.tolven.component.application.jboss-0.0.1.zi
p has been replaced with new file:/C:/tolven/tolven-config/repositoryRuntime/plu
gins/org.tolven.component.application.jboss-0.0.1.zip for {PluginFragment: uid=o
rg.tolven.component.application.jboss@0.0.1} with key org.tolven.component.appli
cation.jboss
18:29:08,820 WARN [ShadingPathResolver] old context URL file:/C:/tolven/tolven-
config/repositoryRuntime/plugins/org.tolven.deploy.pluginframework-0.0.1.zip has
been replaced with new file:/C:/tolven/tolven-config/repositoryRuntime/plugins/
org.tolven.deploy.pluginframework-0.0.1.zip for {PluginFragment: uid=org.tolven.
deploy.pluginframework@0.0.1} with key org.tolven.deploy.pluginframework
18:29:08,929 INFO [TolvenApplicationInitializer] integrity check done: errors -
0, warnings - 0
18:29:08,929 INFO [TolvenApplicationInitializer] application plug-in is org.tol
ven.command
18:29:08,929 INFO [StandardPluginManager] plug-in started - org.tolven.library.
pluginframework@0.0.1 (active/total: 1 of 105)
18:29:08,929 INFO [StandardPluginManager] plug-in started - org.tolven.library.
serverconfig@0.0.2 (active/total: 2 of 105)
18:29:08,945 INFO [StandardPluginManager] plug-in started - org.tolven.command@
0.0.3 (active/total: 3 of 105)
18:29:08,945 INFO [StandardPluginManager] plug-in started - org.tolven.config.d
atabase@0.0.1 (active/total: 4 of 105)
18:29:08,960 INFO [StandardPluginManager] plug-in started - org.tolven.library.
bouncy-castle@0.0.1 (active/total: 5 of 105)
18:29:08,960 INFO [StandardPluginManager] plug-in started - org.tolven.config.l
dap@0.0.1 (active/total: 6 of 105)
18:29:08,976 INFO [AdminAssembler] *** start ***
18:29:09,179 INFO [AdminAssembler] tmpDir - c:\tolven\tolven-config\build\repos
itoryTmp
18:29:09,179 INFO [AdminAssembler] stageDir - c:\tolven\tolven-config\build\rep
ositoryStage
18:29:09,179 INFO [AdminAssembler] devLib - c:\tolven\tolven-config\devLib
18:29:09,195 INFO [AdminAssembler] Admin keystore: c:\tolven\tolven-config\cred
entials\admin\tolvendev-admin.jks
18:29:09,195 INFO [AdminAssembler] Admin truststore: c:\tolven\tolven-config\cr
edentials\admin\tolvendev-admin-cacerts.jks
18:29:09,210 INFO [AdminAssembler] Admin secretkey: c:\tolven\tolven-config\cre
dentials\admin\admin-encryptedSecretKey
18:29:09,210 INFO [AdminAssembler] Admin password store: c:\tolven\tolven-confi
g\credentials\admin\admin-password.cfg
18:29:09,804 INFO [AdminAssembler] LDAP key: c:\tolven\tolven-config\credential
s\ldap\tolvendev-ldap-key.pem
18:29:09,804 INFO [AdminAssembler] LDAP certificate: c:\tolven\tolven-config\cr
edentials\ldap\tolvendev-ldap-cert.pem
18:29:09,804 INFO [AdminAssembler] LDAP truststore: c:\tolven\tolven-config\cre
dentials\ldap\tolvendev-ldap-cacerts.pem
18:29:09,804 INFO [AdminAssembler] LDAPClient key: c:\tolven\tolven-config\cred
entials\ldapclient\tolvendev-ldapclient-key.pem
18:29:09,820 INFO [AdminAssembler] Database keystore: c:\tolven\tolven-config\c
redentials\oracle\tolvendev-oracle.jks
18:29:09,820 INFO [AdminAssembler] Database truststore: c:\tolven\tolven-config
\credentials\oracle\root.crt
18:29:09,835 INFO [AdminAssembler] DatabaseClient key: c:\tolven\tolven-config\
credentials\pgadmin\postgresql.key
18:29:09,835 INFO [AdminAssembler] DatabaseClient certificate: c:\tolven\tolven
-config\credentials\pgadmin\postgresql.crt
18:29:09,851 INFO [AdminAssembler] AppServer keystore: c:\tolven\tolven-config\
credentials\jboss\tolvendev-jboss.jks
18:29:09,851 INFO [AdminAssembler] AppServer truststore: c:\tolven\tolven-confi
g\credentials\jboss\tolvendev-jboss-cacerts.jks
18:29:09,851 INFO [AdminAssembler] MDBUser key: c:\tolven\tolven-config\credent
ials\mdbuser\tolvendev-mdbuser-key.pem
18:29:09,867 INFO [AdminAssembler] MDBUser certificate: c:\tolven\tolven-config
\credentials\mdbuser\tolvendev-mdbuser-cert.pem
18:29:09,867 INFO [AdminAssembler] MDBUser keystore: c:\tolven\tolven-config\cr
edentials\mdbuser\tolvendev-mdbuser.p12
18:29:10,164 INFO [TolvenConfigWrapper] Load JSSE keystore for admin
18:29:10,164 INFO [TolvenConfigWrapper] Load JSSE truststore for admin
18:29:10,164 INFO [AdminAssembler] *** end ***
18:29:10,164 INFO [StandardPluginManager] plug-in started - org.tolven.assemble
r.admin@0.0.4 (active/total: 7 of 105)
18:29:10,179 INFO [StandardPluginManager] plug-in started - org.tolven.library.
jasperreports@0.0.1 (active/total: 8 of 105)
18:29:10,179 INFO [StandardPluginManager] plug-in started - org.tolven.library.
remoteclient@0.0.1 (active/total: 9 of 105)
18:29:10,179 INFO [StandardPluginManager] plug-in started - org.tolven.library.
jboss@0.0.1 (active/total: 10 of 105)
18:29:10,179 INFO [StandardPluginManager] plug-in started - org.tolven.library.
tolvenclient@0.0.2 (active/total: 11 of 105)
18:29:10,179 INFO [StandardPluginManager] plug-in started - org.tolven.library.
javaee@0.0.1 (active/total: 12 of 105)
18:29:10,179 INFO [StandardPluginManager] plug-in started - org.tolven.library.
jdbcdriver@0.0.1 (active/total: 13 of 105)
18:29:10,179 INFO [StandardPluginManager] plug-in started - org.tolven.componen
t.application.jboss@0.0.1 (active/total: 14 of 105)
18:29:10,195 INFO [StandardPluginManager] plug-in started - org.tolven.library.
application@0.0.1 (active/total: 15 of 105)
18:29:10,257 INFO [Application] *** start ***
18:29:10,273 INFO [Application] Starting for user: admin to jnp://localhost:109
9
18:29:10,429 INFO [Application] Update MDBUser mdbuser
18:29:10,429 INFO [TolvenClient] jndi: java.naming.provider.url=jnp://localhost
:1099
18:29:10,429 INFO [TolvenClient] jndi: java.naming.factory.initial=org.jboss.na
ming.NamingContextFactory
18:29:10,429 INFO [TolvenClient] jndi: java.naming.factory.url.pkgs=org.jboss.n
aming:org.jnp.interfaces
18:29:11,523 INFO [LoadMDBUsers] Rolling back transaction : load mdbuser for: a
dmin
Application start failed.
org.java.plugin.PluginLifecycleException: can't start plug-in org.tolven.compone
nt.application@0.0.1
at org.java.plugin.standard.StandardPluginManager.activatePlugin(Standar
dPluginManager.java:415)
at org.java.plugin.standard.StandardPluginManager.activatePlugin(Standar
dPluginManager.java:245)
at org.tolven.command.TolvenApplication.startRequiredPlugins(TolvenAppli
cation.java:87)
at org.tolven.command.TolvenApplication.startApplication(TolvenApplicati
on.java:56)
at org.java.plugin.boot.Boot.boot(Boot.java:346)
at org.java.plugin.boot.Boot.main(Boot.java:243)
at org.tolven.plugin.boot.TPFBoot.main(TPFBoot.java:102)
Caused by: java.lang.RuntimeException: Could not load mdbuser for: admin
at org.tolven.client.load.LoadMDBUsers.updateMDBUser(LoadMDBUsers.java:3
0)
at org.tolven.component.application.Application.updateMDBUser(Applicatio
n.java:152)
at org.tolven.component.application.Application.doStart(Application.java
:123)
at org.java.plugin.Plugin.start(Plugin.java:82)
at org.java.plugin.PluginManager.startPlugin(PluginManager.java:325)
at org.java.plugin.standard.StandardPluginManager.activatePlugin(Standar
dPluginManager.java:407)
... 6 more
Caused by: javax.ejb.EJBTransactionRolledbackException: org.hibernate.exception.
SQLGrammarException: could not execute query
at org.jboss.ejb3.tx.Ejb3TxPolicy.handleInCallerTx(Ejb3TxPolicy.java:87)

at org.jboss.aspects.tx.TxPolicy.invokeInCallerTx(TxPolicy.java:130)
at org.jboss.aspects.tx.TxInterceptor$Required.invoke(TxInterceptor.java
:195)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.
java:101)
at org.jboss.aspects.tx.TxPropagationInterceptor.invoke(TxPropagationInt
erceptor.java:86)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.
java:101)
at org.jboss.ejb3.stateless.StatelessInstanceInterceptor.invoke(Stateles
sInstanceInterceptor.java:62)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.
java:101)
at org.jboss.aspects.security.RoleBasedAuthorizationInterceptor.invoke(R
oleBasedAuthorizationInterceptor.java:166)
at org.jboss.ejb3.security.RoleBasedAuthorizationInterceptor.invoke(Role
BasedAuthorizationInterceptor.java:115)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.
java:101)
at org.jboss.aspects.security.AuthenticationInterceptor.invoke(Authentic
ationInterceptor.java:77)
at org.jboss.ejb3.security.Ejb3AuthenticationInterceptor.invoke(Ejb3Auth
enticationInterceptor.java:110)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.
java:101)
at org.jboss.ejb3.ENCPropagationInterceptor.invoke(ENCPropagationInterce
ptor.java:46)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.
java:101)
at org.jboss.ejb3.asynchronous.AsynchronousInterceptor.invoke(Asynchrono
usInterceptor.java:106)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.
java:101)
at org.jboss.ejb3.stateless.StatelessContainer.dynamicInvoke(StatelessCo
ntainer.java:304)
at org.jboss.aop.Dispatcher.invoke(Dispatcher.java:106)
at org.jboss.aspects.remoting.AOPRemotingInvocationHandler.invoke(AOPRem
otingInvocationHandler.java:82)
at org.jboss.remoting.ServerInvoker.invoke(ServerInvoker.java:795)
at org.jboss.remoting.transport.socket.ServerThread.processInvocation(Se
rverThread.java:573)
at org.jboss.remoting.transport.socket.ServerThread.dorun(ServerThread.j
ava:373)
at org.jboss.remoting.transport.socket.ServerThread.run(ServerThread.jav
a:166)
Caused by: javax.persistence.PersistenceException: org.hibernate.exception.SQLGr
ammarException: could not execute query
at org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException
(AbstractEntityManagerImpl.java:629)
at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:73)
at org.tolven.security.bean.LoginBean.findUser(LoginBean.java:73)
at org.tolven.security.bean.LoginBean.createOrUpdateUser(LoginBean.java:
314)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.
java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces
sorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.
java:112)
at org.jboss.ejb3.interceptor.InvocationContextImpl.proceed(InvocationCo
ntextImpl.java:166)
at org.jboss.ejb3.interceptor.EJB3InterceptorsInterceptor.invoke(EJB3Int
erceptorsInterceptor.java:63)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.
java:101)
at org.jboss.ejb3.entity.TransactionScopedEntityManagerInterceptor.invok
e(TransactionScopedEntityManagerInterceptor.java:54)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.
java:101)
at org.jboss.ejb3.AllowedOperationsInterceptor.invoke(AllowedOperationsI
nterceptor.java:47)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.
java:101)
at org.jboss.aspects.tx.TxPolicy.invokeInCallerTx(TxPolicy.java:126)
at org.jboss.aspects.tx.TxInterceptor$Required.invoke(TxInterceptor.java
:195)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.
java:101)
at org.jboss.aspects.tx.TxPropagationInterceptor.invoke(TxPropagationInt
erceptor.java:86)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.
java:101)
at org.jboss.ejb3.stateless.StatelessInstanceInterceptor.invoke(Stateles
sInstanceInterceptor.java:62)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.
java:101)
at org.jboss.aspects.security.RoleBasedAuthorizationInterceptor.invoke(R
oleBasedAuthorizationInterceptor.java:166)
at org.jboss.ejb3.security.RoleBasedAuthorizationInterceptor.invoke(Role
BasedAuthorizationInterceptor.java:115)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.
java:101)
at org.jboss.aspects.security.AuthenticationInterceptor.invoke(Authentic
ationInterceptor.java:77)
at org.jboss.ejb3.security.Ejb3AuthenticationInterceptor.invoke(Ejb3Auth
enticationInterceptor.java:110)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.
java:101)
at org.jboss.ejb3.ENCPropagationInterceptor.invoke(ENCPropagationInterce
ptor.java:46)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.
java:101)
at org.jboss.ejb3.asynchronous.AsynchronousInterceptor.invoke(Asynchrono
usInterceptor.java:106)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.
java:101)
at org.jboss.ejb3.stateless.StatelessContainer.dynamicInvoke(StatelessCo
ntainer.java:304)
at org.jboss.aop.Dispatcher.invoke(Dispatcher.java:106)
at org.jboss.aspects.remoting.AOPRemotingInvocationHandler.invoke(AOPRem
otingInvocationHandler.java:82)
at org.jboss.remoting.ServerInvoker.invoke(ServerInvoker.java:795)
at org.jboss.remoting.transport.socket.ServerThread.processInvocation(Se
rverThread.java:573)
at org.jboss.remoting.transport.socket.ServerThread.dorun(ServerThread.j
ava:373)
at org.jboss.remoting.transport.socket.ServerThread.run(ServerThread.jav
a:166)
at org.jboss.remoting.MicroRemoteClientInvoker.invoke(MicroRemoteClientI
nvoker.java:163)
at org.jboss.remoting.Client.invoke(Client.java:1634)
at org.jboss.remoting.Client.invoke(Client.java:548)
at org.jboss.aspects.remoting.InvokeRemoteInterceptor.invoke(InvokeRemot
eInterceptor.java:62)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.
java:101)
at org.jboss.aspects.tx.ClientTxPropagationInterceptor.invoke(ClientTxPr
opagationInterceptor.java:67)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.
java:101)
at org.jboss.aspects.security.SecurityClientInterceptor.invoke(SecurityC
lientInterceptor.java:53)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.
java:101)
at org.jboss.ejb3.remoting.IsLocalInterceptor.invoke(IsLocalInterceptor.
java:74)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.
java:101)
at org.jboss.ejb3.stateless.StatelessRemoteProxy.invoke(StatelessRemoteP
roxy.java:107)
at $Proxy19.createOrUpdateUser(Unknown Source)
at org.tolven.client.load.LoadMDBUsers.updateMDBUser(LoadMDBUsers.java:2
5)
at org.tolven.component.application.Application.updateMDBUser(Applicatio
n.java:152)
at org.tolven.component.application.Application.doStart(Application.java
:123)
at org.java.plugin.Plugin.start(Plugin.java:82)
at org.java.plugin.PluginManager.startPlugin(PluginManager.java:325)
at org.java.plugin.standard.StandardPluginManager.activatePlugin(Standar
dPluginManager.java:407)
at org.java.plugin.standard.StandardPluginManager.activatePlugin(Standar
dPluginManager.java:245)
at org.tolven.command.TolvenApplication.startRequiredPlugins(TolvenAppli
cation.java:87)
at org.tolven.command.TolvenApplication.startApplication(TolvenApplicati
on.java:56)
at org.java.plugin.boot.Boot.boot(Boot.java:346)
at org.java.plugin.boot.Boot.main(Boot.java:243)
at org.tolven.plugin.boot.TPFBoot.main(TPFBoot.java:102)
at org.jboss.aspects.remoting.InvokeRemoteInterceptor.invoke(InvokeRemot
eInterceptor.java:74)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.
java:101)
at org.jboss.aspects.tx.ClientTxPropagationInterceptor.invoke(ClientTxPr
opagationInterceptor.java:67)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.
java:101)
at org.jboss.aspects.security.SecurityClientInterceptor.invoke(SecurityC
lientInterceptor.java:53)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.
java:101)
at org.jboss.ejb3.remoting.IsLocalInterceptor.invoke(IsLocalInterceptor.
java:74)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.
java:101)
at org.jboss.ejb3.stateless.StatelessRemoteProxy.invoke(StatelessRemoteP
roxy.java:107)
at $Proxy19.createOrUpdateUser(Unknown Source)
at org.tolven.client.load.LoadMDBUsers.updateMDBUser(LoadMDBUsers.java:2
5)
at org.tolven.component.application.Application.updateMDBUser(Applicatio
n.java:152)
at org.tolven.component.application.Application.doStart(Application.java
:123)
at org.java.plugin.Plugin.start(Plugin.java:82)
at org.java.plugin.PluginManager.startPlugin(PluginManager.java:325)
at org.java.plugin.standard.StandardPluginManager.activatePlugin(Standar
dPluginManager.java:407)
at org.java.plugin.standard.StandardPluginManager.activatePlugin(Standar
dPluginManager.java:245)
at org.tolven.command.TolvenApplication.startRequiredPlugins(TolvenAppli
cation.java:87)
at org.tolven.command.TolvenApplication.startApplication(TolvenApplicati
on.java:56)
at org.java.plugin.boot.Boot.boot(Boot.java:346)
at org.java.plugin.boot.Boot.main(Boot.java:243)
at org.tolven.plugin.boot.TPFBoot.main(TPFBoot.java:102)
Caused by: org.hibernate.exception.SQLGrammarException: could not execute query
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.j
ava:67)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelp
er.java:43)
at org.hibernate.loader.Loader.doList(Loader.java:2223)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2104)
at org.hibernate.loader.Loader.list(Loader.java:2099)
at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:378)
at org.hibernate.hql.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.ja
va:338)
at org.hibernate.engine.query.HQLQueryPlan.performList(HQLQueryPlan.java
:172)
at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1121)
at org.hibernate.impl.QueryImpl.list(QueryImpl.java:79)
at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:64)
at org.tolven.security.bean.LoginBean.findUser(LoginBean.java:73)
at org.tolven.security.bean.LoginBean.createOrUpdateUser(LoginBean.java:
314)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.
java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces
sorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.
java:112)
at org.jboss.ejb3.interceptor.InvocationContextImpl.proceed(InvocationCo
ntextImpl.java:166)
at org.jboss.ejb3.interceptor.EJB3InterceptorsInterceptor.invoke(EJB3Int
erceptorsInterceptor.java:63)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.
java:101)
at org.jboss.ejb3.entity.TransactionScopedEntityManagerInterceptor.invok
e(TransactionScopedEntityManagerInterceptor.java:54)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.
java:101)
at org.jboss.ejb3.AllowedOperationsInterceptor.invoke(AllowedOperationsI
nterceptor.java:47)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.
java:101)
at org.jboss.aspects.tx.TxPolicy.invokeInCallerTx(TxPolicy.java:126)
at org.jboss.aspects.tx.TxInterceptor$Required.invoke(TxInterceptor.java
:195)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.
java:101)
at org.jboss.aspects.tx.TxPropagationInterceptor.invoke(TxPropagationInt
erceptor.java:86)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.
java:101)
at org.jboss.ejb3.stateless.StatelessInstanceInterceptor.invoke(Stateles
sInstanceInterceptor.java:62)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.
java:101)
at org.jboss.aspects.security.RoleBasedAuthorizationInterceptor.invoke(R
oleBasedAuthorizationInterceptor.java:166)
at org.jboss.ejb3.security.RoleBasedAuthorizationInterceptor.invoke(Role
BasedAuthorizationInterceptor.java:115)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.
java:101)
at org.jboss.aspects.security.AuthenticationInterceptor.invoke(Authentic
ationInterceptor.java:77)
at org.jboss.ejb3.security.Ejb3AuthenticationInterceptor.invoke(Ejb3Auth
enticationInterceptor.java:110)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.
java:101)
at org.jboss.ejb3.ENCPropagationInterceptor.invoke(ENCPropagationInterce
ptor.java:46)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.
java:101)
at org.jboss.ejb3.asynchronous.AsynchronousInterceptor.invoke(Asynchrono
usInterceptor.java:106)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.
java:101)
at org.jboss.ejb3.stateless.StatelessContainer.dynamicInvoke(StatelessCo
ntainer.java:304)
at org.jboss.aop.Dispatcher.invoke(Dispatcher.java:106)
at org.jboss.aspects.remoting.AOPRemotingInvocationHandler.invoke(AOPRem
otingInvocationHandler.java:82)
at org.jboss.remoting.ServerInvoker.invoke(ServerInvoker.java:795)
at org.jboss.remoting.transport.socket.ServerThread.processInvocation(Se
rverThread.java:573)
at org.jboss.remoting.transport.socket.ServerThread.dorun(ServerThread.j
ava:373)
at org.jboss.remoting.transport.socket.ServerThread.run(ServerThread.jav
a:166)
Caused by: java.sql.SQLException: ORA-00932: inconsistent datatypes: expected -
got BLOB

at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java
:112)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:331)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:288)
at oracle.jdbc.driver.T4C8Oall.receive(T4C8Oall.java:745)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.
java:216)
at oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPrepare
dStatement.java:810)
at oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStateme
nt.java:1039)
at oracle.jdbc.driver.T4CPreparedStatement.executeMaybeDescribe(T4CPrepa
redStatement.java:850)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStateme
nt.java:1134)
at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePrep
aredStatement.java:3339)
at oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePrepare
dStatement.java:3384)
at org.jboss.resource.adapter.jdbc.WrappedPreparedStatement.executeQuery
(WrappedPreparedStatement.java:236)
at org.hibernate.jdbc.AbstractBatcher.getResultSet(AbstractBatcher.java:
186)
at org.hibernate.loader.Loader.getResultSet(Loader.java:1787)
at org.hibernate.loader.Loader.doQuery(Loader.java:674)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Lo
ader.java:236)
at org.hibernate.loader.Loader.doList(Loader.java:2220)
... 46 more
Press any key to continue . . .


And the JBoss Server logs showed:
2009-07-07 18:29:11,398 WARN [org.hibernate.util.JDBCExceptionReporter] SQL Error: 932, SQLState: 42000
2009-07-07 18:29:11,398 ERROR [org.hibernate.util.JDBCExceptionReporter] ORA-00932: inconsistent datatypes: expected - got BLOB


After enabling full DEBUG logging for JBoss server AND Hibernate, the problem was identified as an incorrect SQL Query (see ORA-00932: inconsistent datatypes: expected - got BLOB)!

The basic problem was a wrong SQL query formed by Hibernate - the TOLVENUSER table has 3 columns of type BLOB and the query in question was "SELECT DISTINCT...". Whereas "DISTINCT" does not work with blob columns (in Oracle 10g anyway) and hence the oracle error: ORA_00932.

The approach I had was to customise the offending query to simply remove "DISTINCT", especially since TOLVENUSER table already has a primary key on ID column anyway - the "DISTINCT" was hence redundant in the first place.
This was done by updating a single Java file, org.tolven.security.bean.LoginBean (under TolvenEJB module). In the findUser( String principal) method, find the following line and remove "DISTINCT":
String select = "SELECT DISTINCT u FROM TolvenUser u WHERE u.ldapUID = :principal " +

I then updated this compiled class file direclty into the tolvenEJB.jar file in JBoss's tolven ear file (at "...tolven-jboss-4.2.2.GA\server\tolven\deploy\tolven.ear/tolvenEJB.jar") and restarted Jboss.

And it was smooth running all the way after that (configPhase3 and so on). I'm accessing all Tolven web app pages perfectly now.
 
Superblog Directory