DataSource über @Ressource injezieren

BLR

Erfahrenes Mitglied
Hallo zusammen :)
in meiner Business Logik Schicht brauche ich eine Funktion, die als Parameter meine Datenbank-Verbindung braucht.
Diese Datenbankverbindung wollte ich zur nächst vom EntityManager holen, was mir nicht gelungen ist.
Ich habe da versucht was zu casten, aber aber nicht geht.
Jetzt denke ich über die Injezierung nach, wie in einigen Beispielen in Google zu finden ist.
Eigentlich nicht schwer, aber er findet bei mir die Injektion nicht.

So sieht die Persistence.xml aus:

Code:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
  <persistence-unit name="meinPU" transaction-type="JTA">
  <jta-data-source>jdbc/mssql</jta-data-source>
  <exclude-unlisted-classes>false</exclude-unlisted-classes>
  <properties/>
  </persistence-unit>
</persistence>

Die Klasse, wo ich die injezieren will:

Java:
@Stateless
public class AngebotEJB extends AbstractEntityEJB<Angebot> {
  
  @PersistenceContext(unitName = "EJBsPU")
  private EntityManager em;
  
  @Resource(name = "jdbc/mssql")
  private DataSource ds;

@Override
  protected EntityManager getEntityManager() {
  return em;
  }
  public void generateAngebot(int id) throws Exception {
  
  Connection connection = ds.getConnection();
}
}

Und die Fehlermeldung:

".env.mssql] fehlt",

Vllt muss man die Ressource im Deployment-Descriptor auch definieren??
Danke für jeden Tipp.
 

saftmeister

Nutze den Saft!
Hi,

die persistence.xml kommt nicht zum Tragen, wenn du eine DataSource injizieren willst. Die wird erst dann herangezogen, wenn man den EntityManager über @PersistenceContext injecten will. Dort wird dann das Attribute "unitName" mit dem Namen aus der persistence.xml verwendet. Für die Verwendung eines EntityManager ist ein DataSource-Objekt jedoch nicht notwendig.

Wie sieht die Konfiguration der DataSource innerhalb deines Enterprise-Containers aus? Bei Wildfly ist es bspw. die standalone.xml. Hier mal ein Beispiel für die Konfiguration in einer standalone.xml:

XML:
        <subsystem xmlns="urn:jboss:domain:datasources:3.0">
            <datasources>
               <datasource jndi-name="java:/jdbc/books-database" pool-name="books-datasource" enabled="true">
                    <connection-url>jdbc:mysql://127.0.0.1:3306/test</connection-url>
                    <driver>mysql-connector-java-5.1.36.jar_com.mysql.jdbc.Driver_5_1</driver>
                    <security>
                        <user-name>test</user-name>
                        <password>test</password>
                    </security>
                </datasource>

Und wie es dann in der Bean verwendet wird:

Java:
package de.tutorials.testing;

import javax.annotation.Resource;
import javax.ejb.Remote;
import javax.ejb.Stateless;
import javax.sql.DataSource;

@Stateless
@Remote(DataSourceTest.class)
public class DataSourceTestBean implements DataSourceTest {

    @Resource(lookup = "java:/jdbc/books-database")
    private DataSource dataSource;

    public String sayHello() {
        try {
            return new String("isClosed():" + dataSource.getConnection().isClosed());
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

Ausgabe am Client:

Code:
isClosed():false
 
  • Gefällt mir
Reaktionen: BLR

BLR

Erfahrenes Mitglied
Vielen, dass du etwas Lichts ins Dunkle bringst.

Mein Datasource-Abschnitt in der standalone.xml vom jboss 6.4 sieht so aus:


Code:
 <datasources>
  <datasource jndi-name="java:jboss/datasources/ExampleDS" pool-name="ExampleDS" enabled="true" use-java-context="true">
  <connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE</connection-url>
  <driver>h2</driver>
  <security>
  <user-name>sa</user-name>
  <password>sa</password>
  </security>
  </datasource>
  <drivers>
  <driver name="h2" module="com.h2database.h2">
  <xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
  </driver>
  <driver name="mssql" module="mssql">
  <driver-class>com.microsoft.sqlserver.jdbc.SQLServerDriver</driver-class>
  <xa-datasource-class>com.microsoft.sqlserver.jdbc.SQLServerXADataSource</xa-datasource-class>
  </driver>
  </drivers>
  </datasources>

Ich kommuniziere mit dem microsoft sql-server.
Wie man an der xml erkennt, habe ich gar kein Datasource, welches ich für microsoft slq-server verwenden konnte bzw. denke das so.
Die einzige Datasource ist die "java:jboss/datasources/ExampleDS"

Und wenn ich schreibe:
Code:
@Resource(lookup = ""java:jboss/datasources/ExampleDS")
private DataSource ds;

Irgendwie muss ich wohl zu erst eine Datasource für mein mssql definieren
 

BLR

Erfahrenes Mitglied
Ich habe nun die Datasource für MSSQL 2012 erstellt.
Folgende Einträge habe ich gemacht:
Standalone.xml

Code:
<datasource jndi-name="java:jboss/datasources/mydb" pool-name="mydb" enabled="true" use-java-context="true">
  <connection-url>jdbc:jtds:sqlserver://W7-DEPDB4288\SQLEXPRESS:1433/visdb;loginTimeout=30</connection-url>
  <driver>JTDS</driver>
  <new-connection-sql>select 1</new-connection-sql>
  <transaction-isolation>TRANSACTION_READ_COMMITTED</transaction-isolation>
  <pool>
  <min-pool-size>5</min-pool-size>
  <max-pool-size>50</max-pool-size>
  </pool>
  <security>
  <user-name>sa</user-name>
  <password>a</password>
  </security>
  <validation>
  <check-valid-connection-sql>select 1</check-valid-connection-sql>
  </validation>
  <timeout>
  <set-tx-query-timeout>true</set-tx-query-timeout>
  <blocking-timeout-millis>5000</blocking-timeout-millis>
  <idle-timeout-minutes>15</idle-timeout-minutes>
  </timeout>
  <statement>
  <track-statements>false</track-statements>
  </statement>
  </datasource>     
           <driver name="mssql" module="mssql">
             <driver-class>com.microsoft.sqlserver.jdbc.SQLServerDriver</driver-class>
             <xa-datasource-class>com.microsoft.sqlserver.jdbc.SQLServerXADataSource</xa-datasource-class>
           </driver>
         </drivers>
       </datasources>

in meiner Persistence.xml habe ich folgendes geschrieben:

Code:
<jta-data-source>java:jboss/datasources/mydb</jta-data-source>
  <exclude-unlisted-classes>false</exclude-unlisted-classes>

und die Injection:


Java:
@PersistenceContext(unitName = "EJBsPU")
  private EntityManager em;
@Resource(lookup = "java:jboss/datasources/mydb")
  private DataSource ds;

Leider läufts noch nicht:
Jboss Applicationsserver:

ERROR [org.jboss.as.controller.management-operation] (DeploymentScanner-threads - 2) JBAS014612: Operation ("deploy") fehlgeschlagen - Adresse: ([("deployment" => "myserver.ear")]) - Fehlerbeschreibung: {"JBAS014771: Dienste mit fehlenden/unverfügbaren Abhängigkeiten " => [
"jboss.naming.context.java.comp.myserver.\"myserver-ejb-0.0.1-SNAPSHOT\".myEJB.env.\"server.ejb.myEJB\".ds [jboss.naming.context.java.jboss.datasources.mydb] fehlt",

und der RUN steht:



Deploying C:\app\ear\target\myserver.ear
{"JBAS014653: Zusammengesetzte Operation ist fehlgeschlagen und wurde zurückgesetzt. Die Schritte die fehlgeschlagen sind: " => {"Operation step-2" => {"JBAS014771: Dienste mit fehlenden/unverfügbaren Abhängigkeiten " => [
"jboss.naming.context.java.comp.myserver.\"myserver-ejb-0.0.1-SNAPSHOT\".myEJB.env.\"server.ejb.myEJB\".ds [jboss.naming.context.java.jboss.datasources.mydb] fehlt",
"jboss.persistenceunit.\"myserver.ear/myserver-ejb-0.0.1-SNAPSHOT.jar#EJBsPU\" [jboss.naming.context.java.jboss.datasources.mydb] fehlt",
"jboss.naming.context.java.module.myserver.\"myserver-war-0.0.1-SNAPSHOT\".env.\"server.ejb.myEJB\".ds [jboss.naming.context.java.jboss.datasources.mydb] fehlt",
"jboss.persistenceunit.\"myserver.ear/myserver-war-0.0.1-SNAPSHOT.war#EJBsPU\" [jboss.naming.context.java.jboss.datasources.mydb] fehlt"
]}}}

Warum findet er bloß die Datasource nicht??
 
Zuletzt bearbeitet:

BLR

Erfahrenes Mitglied
Sorry, habs noch angepasst.....^^ schaue oben
Also den Post um 11:25
 
Zuletzt bearbeitet:

saftmeister

Nutze den Saft!
Die Angabe bei driver in der DataSource-Konfiguration scheint nicht zu passen:

XML:
<driver>JTDS</driver>

sollte wahrscheinlich

XML:
<driver>mssql</driver>

korrespondierend zum driver-Eintrag sein. Ich denke mal, dass er die Datasource auch gar nicht deployen konnte (schau mal im Log ob so was kommt wie

Code:
11:32:56,486 INFO  [org.jboss.as.connector.deployers.jdbc] (MSC service thread 1-8) WFLYJCA0005: Deploying non-JDBC-compliant driver class com.mysql.jdbc.Driver (version 5.1)
11:32:56,489 INFO  [org.jboss.as.connector.deployers.jdbc] (MSC service thread 1-8) WFLYJCA0005: Deploying non-JDBC-compliant driver class com.mysql.fabric.jdbc.FabricMySQLDriver (version 5.1)
11:32:56,499 INFO  [org.jboss.as.connector.deployers.jdbc] (MSC service thread 1-8) WFLYJCA0018: Started Driver service with driver-name = mysql-connector-java-5.1.36.jar_com.mysql.fabric.jdbc.FabricMySQLDriver_5_1
11:32:56,500 INFO  [org.jboss.as.connector.deployers.jdbc] (MSC service thread 1-7) WFLYJCA0018: Started Driver service with driver-name = mysql-connector-java-5.1.36.jar_com.mysql.jdbc.Driver_5_1
11:32:56,501 INFO  [org.jboss.as.connector.subsystems.datasources] (MSC service thread 1-3) WFLYJCA0001: Bound data source [java:/jdbc/books-database]
11:32:57,718 INFO  [org.jboss.as.server] (Controller Boot Thread) WFLYSRV0010: Deployed "mysql-connector-java-5.1.36.jar" (runtime-name : "mysql-connector-java-5.1.36.jar")

statt mysql bei dir dann natürlich mssql :)

Die ExampleDS sollte auf jeden Fall deployen:

Code:
11:32:55,279 INFO  [org.jboss.as.connector.subsystems.datasources] (ServerService Thread Pool -- 33) WFLYJCA0004: Deploying JDBC-compliant driver class org.h2.Driver (version 1.3)
.....
11:32:55,934 INFO  [org.jboss.as.connector.subsystems.datasources] (MSC service thread 1-6) WFLYJCA0001: Bound data source [java:jboss/datasources/ExampleDS]

Also einen Schritt nach dem anderen. Erst schauen, ob deine DataSource im Log als Deployed auftaucht. Das kannst du rein theoretisch auch über die Web-Console prüfen, aber im Log genügt erst mal.

Ist das erledigt, kannst du prüfen, ob ein Persistenz-Kontext erstellt wurde. Das sollte dann ungefähr so im Log aussehen:

Code:
11:38:36,285 INFO  [org.jboss.as.jpa] (ServerService Thread Pool -- 58) WFLYJPA0010: Starting Persistence Unit (phase 1 of 2) Service 'ejb-test-ear.ear/ejb-test-ejb.jar#booksPU'

Ein Persistenz-Kontext verwendet eine DataSource-Konfiguration (macht prinzipiell das gleiche wie meine Bean) und injiziert dann eine Instanz der DataSource in den Kontext, der dann vom EntityManager verwendet wird.

Also gemäß diesem Schema

DataSource-Konfiguration => Persistenz-Kontext (persistence.xml) => EntityManager (unitName = Name der Persistenz-Einheit aus der persistence.xml)
 

BLR

Erfahrenes Mitglied
Ich habs geschafft!!!
Es lag an der falschen Angabe vom "Driver".
Danach war die falsche Connection-URL da.
Diese soltle dann so aussehen:
<connection-url>jdbc:sqlserver://linp-sqlrpt-01;databaseName=pmdm</connection-url>
 

BLR

Erfahrenes Mitglied
Ja, Es funktioniert jetzt alles, was das Deployen angeht.
Allerdings kann ich mich nicht mehr anmelden^^

Früher hat es natürlich funktioniert, bevor ich das DataSource und die Injection eingebaut habe.

Nun kriege ich die Meldung beim Einlogen: Login failed. Please check your login credentials.
An meiner Security-Domain habe ich nichts geändert.....
Verstehe nicht, wie das eine mit dem anderen zusammenhängt und ob das überhaupt miteinander zusammenhängt.
Wenn ich lediglich auf "Play" drücke sagt Jboss in der Console:
Security role name superuser used in an <auth-constraint> without being defined in a <security-role>

Aber ich habe da nichts geändert....
So siehts bei mir aus:

Code:
<security-domain name="mySecurity" cache-type="default">
  <authentication>
  <login-module code="org.jboss.security.auth.spi.LdapLoginModule" flag="required">
  <module-option name="password-stacking" value="useFirstPass"/>
  <module-option name="java.naming.factory.initial" value="com.sun.jndi.ldap.LdapCtxFactory"/>
  <module-option name="java.naming.provider.url" value="ldap://depdbdc01.wincor-nixdorf.com/"/>
  <module-option name="java.naming.security.authentication" value="DIGEST-MD5 GSSAPI"/>
  <module-option name="rolesCtxDN" value="ou=None,dc=myHouse,dc=com"/>
  </login-module>
  <login-module code="Database" flag="required">
  <module-option name="password-stacking" value="useFirstPass"/>
  <module-option name="dsJndiName" value="jdbs/mssql"/>
  <module-option name="principalsQuery" value="select login from user where login = ?"/>
  <module-option name="rolesQuery" value="select role,'Roles' from user_role where login = ?"/>
  </login-module>
  </authentication>
  </security-domain>

Und so sieht meine Datasource aus:

Code:
 <datasource jndi-name="java:jboss/datasources/mydb" pool-name="mydb" enabled="true" use-java-context="true">
  <connection-url>jdbc:sqlserver://W7-DEPDB4288\SQLEXPRESS:1433;databaseName=mydb;</connection-url>
  <driver>mssql</driver>
  <security>
  <user-name>sa</user-name>
  <password>a</password>
  </security>
  </datasource>

<driver name="mssql" module="mssql">
  <driver-class>com.microsoft.sqlserver.jdbc.SQLServerDriver</driver-class>
  <xa-datasource-class>com.microsoft.sqlserver.jdbc.SQLServerXADataSource</xa-datasource-class>
  </driver>

Hinweis: Die Tabellen "user" und "user_role" liegen in der gleichen DB wie die anderen Tabellen.
Also Security-Daten und die normale Daten sind in einer DB.
Vllt. liegts am JNDI-Namen in der:

<module-option name="dsJndiName" value="jdbs/mssql"/>
Aber wenn ich diesen value-Wert "jdbs/mssql" in der Datasource, persistence.xml und der ejb verwende, dann kann ich nicht deployen.

Alles wird deployed und ich kanns im Browser erreichen, aber ich kann mich nicht mehr anmelden.....
 
Zuletzt bearbeitet: