0 Replies Latest reply on Sep 20, 2012 10:23 AM by valia981

    PicketBox - DataBaseAttributeLocator

    valia981

      Hi all,

      I've got an error using DatabaseAttributeLocator and I can't find a solution:

      I'm deploying under jboss-as-7.1 a web application (this should be my PDP).

      I have a simple main class which builds a XACML request, sends it to my PDP and waits for response.

       

      Following this tutorial https://community.jboss.org/wiki/XACMLAttributeLocatorUsingTheDatabase I configure my web application to use database if some attribute in request is missing. I've created a simple database (MySQL), inserted correct values, checked connection (with another test program) and this is my pdp configuration

       

      <ns:jbosspdp xmlns:ns="urn:jboss:xacml:2.0">
      ......
      ......
          <ns:Locator Name="org.jboss.security.xacml.locators.attrib.DatabaseResourceAttributeLocator">   
            <ns:Option Name="DATABASE_FILE_NAME">database.file.properties</ns:Option>  
            <ns:Option Name="sql">SELECT account_status FROM AccountStatus where subject_id=?;</ns:Option>  
            <ns:Option Name="attributeSupportedId">urn:xacml:2.0:interop:example:resource:account-status</ns:Option> 
            <ns:Option Name="preparedStatementValue">urn:xacml:2.0:interop:example:resource:owner-id</ns:Option>  
            <ns:Option Name="valueDataType">http://www.w3.org/2001/XMLSchema#string</ns:Option>   
            <ns:Option Name="columnName">account_status</ns:Option> 
          </ns:Locator> 
        </ns:Locators>
      </ns:jbosspdp>
      

       

      and property file contains

       

      connectionURL=jdbc\:mysql\://localhost\:3306/XACMLDBAttributeLocator#and credential
      driverName=com.mysql.jdbc.Driver
      

       

      ConnectionURL is correct.

       

      After this, I create my PDP.war, deploy it using jboss as 7.1, run my main and I've got an exception (ClassNotFound).

       

      15:31:11,818 DEBUG [org.jboss.tm.TransactionManagerLocator] (MSC service thread 1-2) Unable to instantiate legacy transaction manager: java.lang.ClassNotFoundException: org.jboss.tm.TxManager from [Module "org.jboss.jboss-transaction-spi:main" from local module loader @adb1d4 (roots: /home/myhome/jboss-as-7.1.1.Final/modules)]
                at org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:190)
                at org.jboss.modules.ConcurrentClassLoader.performLoadClassUnchecked(ConcurrentClassLoader.java:468)
                at org.jboss.modules.ConcurrentClassLoader.performLoadClassChecked(ConcurrentClassLoader.java:456)
                at org.jboss.modules.ConcurrentClassLoader.performLoadClassChecked(ConcurrentClassLoader.java:423)
                at org.jboss.modules.ConcurrentClassLoader.performLoadClass(ConcurrentClassLoader.java:398)
                at org.jboss.modules.ConcurrentClassLoader.loadClass(ConcurrentClassLoader.java:120)
                at java.lang.Class.forName0(Native Method) [rt.jar:1.6.0_29]
                at java.lang.Class.forName(Class.java:169) [rt.jar:1.6.0_29]
                at org.jboss.tm.TransactionManagerLocator.usePrivateAPI(TransactionManagerLocator.java:172) [jboss-transaction-spi-7.0.0.Final.jar:7.0.0.Final]
                at org.jboss.tm.TransactionManagerLocator.locate(TransactionManagerLocator.java:133) [jboss-transaction-spi-7.0.0.Final.jar:7.0.0.Final]
                at org.jboss.tm.TransactionManagerLocator.locateTransactionManager(TransactionManagerLocator.java:94) [jboss-transaction-spi-7.0.0.Final.jar:7.0.0.Final]
                at org.jboss.tm.usertx.client.ServerVMClientUserTransaction.<init>(ServerVMClientUserTransaction.java:93) [jboss-transaction-spi-7.0.0.Final.jar:7.0.0.Final]
                at org.jboss.tm.usertx.client.ServerVMClientUserTransaction.<clinit>(ServerVMClientUserTransaction.java:60) [jboss-transaction-spi-7.0.0.Final.jar:7.0.0.Final]
                at org.jboss.as.txn.service.ArjunaTransactionManagerService.start(ArjunaTransactionManagerService.java:115) [jboss-as-transactions-7.1.1.Final.jar:7.1.1.Final]
                at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1811) [jboss-msc-1.0.2.GA.jar:1.0.2.GA]
                at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1746) [jboss-msc-1.0.2.GA.jar:1.0.2.GA]
                at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) [rt.jar:1.6.0_29]
                at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) [rt.jar:1.6.0_29]
                at java.lang.Thread.run(Thread.java:662) [rt.jar:1.6.0_29]
      

       

       

      It seems a CLASSPATH problem, com.mysql.jdbc.Driver cannot be found.

      I've tried to specify mysql driver in different ways:

       

      1. lib folder of my web application
      2. jboss module (creating following jboss tutorials)
      3. in CLASSPATH

       

      and I've always got the same error.
      Then I've searched for source code and my error is generated here (class org.jboss.security.xacml.locators.attrib.DatabaseAttributeLocator)

       

      @Override
                protected Connection getConnection() {
      
      
                          Connection connection = null;
                          if (dsJNDIName != null) {
                                    try {
                                              Context ctx = new InitialContext();
                                              DataSource ds = (DataSource) ctx.lookup(dsJNDIName);
                                              connection = ds.getConnection();
                                    } catch (Exception e) {
                                        // log section
                                    }
                          }
                          if (connection == null && dbFileName != null) {
                                    Properties props = new Properties();
                                    ClassLoader tcl = SecurityActions.getContextClassLoader();
                                    try {
                                              props.load(tcl.getResourceAsStream(dbFileName));
                                    } catch (IOException e) {
                                              throw new RuntimeException("Error loading DB file", e);
                                    }
      
      
                                    try {
                                              Class.forName(props.getProperty("driverName"));
                                    } catch (ClassNotFoundException e) {
                                              throw new RuntimeException("DB Driver not found:", e);
                                    }
                                    try {
                                              connection = DriverManager.getConnection(props
                                                                  .getProperty("connectionURL"));
                                    } catch (SQLException e) {
                                              throw new RuntimeException("Cannot get DB Connection:", e);
                                    }
                          }
                          return connection;
                }
      

       

       

      How I can fix this? if I can specify my external database (mysql, h2, db2 for example) only using properties in database.file.properties, where driver files should go?

       

      After hours of works I wrote this class

       

      public class MyDataBaseAttributeLocator extends DatabaseResourceAttributeLocator {
      
      
                @Override
                protected Connection getConnection() {
      
      
                          Connection connection = null;
                          if (dsJNDIName != null) {
                                    try {
                                              Context ctx = new InitialContext();
                                              DataSource ds = (DataSource) ctx.lookup(dsJNDIName);
                                              connection = ds.getConnection();
                                    } catch (Exception e) {
                                          // log section
                                    }
                          }
                          if (connection == null && dbFileName != null) {
                                    Properties props = new Properties();
                                    ClassLoader tcl = SecurityActions.getContextClassLoader();
                                    try {
                                              props.load(tcl.getResourceAsStream(dbFileName));
                                    } catch (IOException e) {
                                              throw new RuntimeException("Error loading DB file", e);
                                    }
      
      
                                    try {
                                              Class.forName(props.getProperty("driverName"), true, tcl);
                                    } catch (ClassNotFoundException e) {
                                              throw new RuntimeException("DB Driver not found:", e);
                                    }
                                    try {
                                              connection = DriverManager.getConnection(props
                                                                  .getProperty("connectionURL"));
                                    } catch (SQLException e) {
                                              throw new RuntimeException("Cannot get DB Connection:", e);
                                    }
                          }
                          return connection;
                }
      }
      

       

       

      the only change is in Class.forName method used.
      Putting my driver in lib directory of web app everything is ok.

      Is my solution correct? I mean, which classloader should be used to find out driver?

      In this case ModuleClassLoader cannot find driver, but I have no limit about database type (or I can't find where this limit is written) and there is no reason to use ModuleClassLoader to load driver...am I wrong?

       

       

       

      Please, If the section is wrong, tell me where my question should go.