I am trying to write a simple query using QueryDSL, but my attempt fails with the following exception.
Caused by: javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file: java.naming.factory.initial
I tried executing query the following ways.
SessionFactory sf = new Configuration().configure().buildSessionFactory();
Session session = sf.openSession();
JPQLQuery query = new HibernateQuery(session);
QClient t = QClient.client;
List<Client> lst = query.from(t).list(t);
System.out.println(lst.size());
And another way.
EntityManagerFactory emf =
Persistence.createEntityManagerFactory("my.package.entities");
EntityManager em = emf.createEntityManager();
JPAQuery query = new JPAQuery(em);
QClient t = QClient.client;
List<Client> lst = query.from(t).list(t);
System.out.println(lst.size());
As stated, both this ways failed with the same exception.
I am using Postrges DB, and the parameters are specified in hibernate.cfg.xml.
Do I need to setup something more for this to work?
The javax.naming package comprises the JNDI API. Since it's just an API, rather than an implementation, you need to tell it which implementation of JNDI to use. The implementations are typically specific to the server you're trying to talk to.
To specify an implementation, you pass in a Properties object when you construct the InitialContext. These properties specify the implementation to use, as well as the location of the server. The default InitialContext constructor is only useful when there are system properties present, but the properties are the same as if you passed them in manually.
As to which properties you need to set, that depends on your server. You need to hunt those settings down and plug them in.
Sample:
Properties properties = new Properties();
properties.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
properties.put(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces");
properties.put("jnp.socket.Factory", "org.jnp.interfaces.TimedSocketFactory");
properties.setProperty("java.naming.provider.url", "jnp://" + remoteHost + :1099");
context = new InitialContext(properties);
or
look for this
Issue
Related
I'm working with existing Java code wherein there is an existing JDBC connection pooling mechanism on deployed systems and an already existing setup to get JDBC connections. I'd like to leverage this to create a MyBatis SqlSession object without creating a Configuration, DataSource, and other things
I have code that already creates a java.sql.Connection object is given the desired resource. I'd like to leverage this and get that SqlSession object and use MyBatis from that point onwards.
I don't want MyBatis to manage connection pooling, determining which data source to use, etc. Is this possible?
I'm afraid you can't avoid creation of the Configuration object. It is used by the internal mybatis machinery like executors. But even if you could it will not help you much. In this case you will need to implement most of Configuration functionality yourself so it does not make sense to do that.
You main goal is to be able to use SqlSessionFactory.openSession(Connection connection) method. To do this you need to have SqlSessionFactory. The easiest way for you is to create Configuration like it is descried in mybatis documentation:
TransactionFactory transactionFactory = new JdbcTransactionFactory();
Environment environment = new Environment("development", transactionFactory, dataSource);
Configuration configuration = new Configuration(environment);
// set properties to configuration here
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(configuration);
Now if your connection pool does implement DataSource you use it directly to create environment. If it does not you need to create an adapter around your pool which implements javax.sql.DataSource.
My solution is similar to Roman's above, but I needed to create an Oracle datasource. For various reasons, the connection needs to be created using the Class.forName type sequence
Class.forName("oracle.jdbc.driver.OracleDriver");
String connectionString = "jdbc:oracle:thin:#//yadayada";
String username = "myusername";
String password = "mypassword";
OracleDataSource oracleDataSource = new OracleDataSource();
oracleDataSource.setURL(connectionString);
oracleDataSource.setPassword(password);
oracleDataSource.setUser(username);
environment = new Environment("dev",transactionFactory,oracleDataSource);
configuration = new Configuration(environment);
configuration.addMappers("MyMybatisMapper");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);
return sqlSessionFactory.openSession();
What I was missing was the OracleDataSource object.
In my Shiro application, I am using the JndiRealmFactory to define my realms. I Register my realms like this:
Hashtable<String, String> args = new Hashtable<>();
args.put(Context.INITIAL_CONTEXT_FACTORY, "org.apache.openejb.client.LocalInitialContextFactory");
InitialContext ctx = new InitialContext(args);
ctx.bind("realms/MyRealm", myRealm);
However, Shiro cannot find realms/MyRealm. I think the reason is, that I Need to define the JndiRealmFactory's jndiEnvironment, which contains the Context.INITIAL_CONTEXT_FACTORY property. However, I don't know how to set this property in my shiro.ini:
realmFactory.jndiEnvironment = ?
I am running my application on TomEE.
My current shiro.ini looks like this:
realmFactory = org.apache.shiro.realm.jndi.JndiRealmFactory
realmFactory.jndiNames = realms/MyRealm
you are not supposed to bind at runtime anything in the EE context. You can probably define it in tomcat as a resource or resources.xml (tomee specific) then just use a standard lookup to read the value (no special properties passed to InitialContext.
I am creating a Drools stateful session as described in the JBPM persistence documentation:
http://docs.jboss.org/jbpm/v5.1/javadocs/org/drools/persistence/jpa/JPAKnowledgeService.html
However, I came across the following exception
javax.persistence.TransactionRequiredException: joinTransaction has been called on a resource-local EntityManager which is unable to register for a JTA transaction.
My code is :
EntityManagerFactory emf = Persistence.createEntityManagerFactory("metadata.model");
Environment env = KnowledgeBaseFactory.newEnvironment();
env.set(EnvironmentName.ENTITY_MANAGER_FACTORY, emf);
env.set(EnvironmentName.TRANSACTION_MANAGER, TransactionManagerServices.getTransactionManager());
env.set(EnvironmentName.TRANSACTION, TransactionManagerServices.getTransactionManager());
KieServices ks = KieServices.Factory.get();
KieContainer kContainer = ks.getKieClasspathContainer();
KieBase kBase = kContainer.getKieBase();
StatefulKnowledgeSession kSession = JPAKnowledgeService.newStatefulKnowledgeSession(kBase, null, env);
The exception is thrown at the last line. Beforehand, I have bound the JDBC JTA Datasource as described in the aforementioned documentation.
PoolingDataSource ds = new PoolingDataSource();
ds.setUniqueName("jdbc/BitronixJTADataSource");
ds.setClassName("com.mysql.jdbc.jdbc2.optional.MysqlXADataSource");
ds.setMaxPoolSize(3);
ds.setAllowLocalTransactions(true);
ds.getDriverProperties().put("user", "root");
ds.getDriverProperties().put("password", "****");
ds.getDriverProperties().put("URL", "jdbc:mysql://localhost:3306/metadatadb");
ds.init();
I am using the EclipseLink persistence provider alongside the MySQL JDBC driver.
Finally, I have made it work. The most important mistake I was making was that I was trying to use EclipseLink as JPA provider. This approach will not work, since besides the custom persistency classes, Drools uses two other persistency-annotated classes: org.drools.persistence.info.SessionInfo and org.drools.persistence.info.WorkItemInfo. These two contain Date fields which are not annotated with the JPA Temporal annotation. They appear to be tailored specifically for Hibernate.
Another important aspect that came to my attention is the need to add the following line after setting the environment variable:
env.set(EnvironmentName.OBJECT_MARSHALLING_STRATEGIES,
new ObjectMarshallingStrategy[] {
new JPAPlaceholderResolverStrategy(domainEnv),
new SerializablePlaceholderResolverStrategy(
ClassObjectMarshallingStrategyAcceptor.DEFAULT) });
This is performed in order to announce your intention to persist the current session state using JPA.
The exception I mentioned above was, however, due to the fact that EclipseLink was creating a "ResourceLocal" transaction wrapper even though JTA was explicitly specified in persistence.xml. This is due to the fact that there was no target-server property specified. Consequently, there were no external transaction controllers attached to the database session that was created and the wrapper that was provided simply couldn't support the joinTransaction operation. To work around this issue, add the following line to your persistence.xml file:
<property name="eclipselink.target-server" value="JBoss"/>
and before initializing the datasource, add:
Configuration conf = TransactionManagerServices.getConfiguration();
conf.setJndiUserTransactionName("java:/TransactionManager");
Of course, I am presuming that BTM is being used.
"javax.naming.Context" is commonly used inside Java EE development. It's quite convenient to use it to establish dynamical database connection by calling its lookup function with given names of resources inside context.xml. The sample code is shown as following where "db_name" is the name you used to identify the database resource.
Context ctx = new InitialContext();
DataSource ds = ctx.lookup("java:comp/env/jdbc/db_name");
My concern is what are the differences between lookup resources by using the same context and lookup resources by using different contexts. And which approach makes more sense or suitable? Suppose all database resources are defined inside the same context.xml file. For example:
Context ctx = new InitialContext();
DataSource ds1 = ctx.lookup("java:comp/env/jdbc/db_name_ds1");
DataSource ds2 = ctx.lookup("java:comp/env/jdbc/db_name_ds2");
and
Context ctx_ds1 = new InitialContext();
Context ctx_ds2 = new InitialContext();
DataSource ds1 = ctx_ds1.lookup("java:comp/env/jdbc/db_name_ds1");
DataSource ds2 = ctx_ds2.lookup("java:comp/env/jdbc/db_name_ds2");
Thank you for your sharing.
there is no difference except you created an unnecessary extra java object. however, if the jndi server was remote, you would have created two different network connections and iverhead of managing them - definetly not what one should do.
So I have a Java/JPA2.0 (EclipseLink) app that connects to a MySQL database. My intention is just passing a JAR file around with a db.properties file. The db.properties should contain the server host address, username, password, etc so that the end user can just plug that in and start using the JAR in their projects.
Currently, I just used Netbeans to create a persistence.xml file with the credentials and that works. But how do I implement the properties file?
My EntityManager class:
public class Factories {
private static final EntityManagerFactory entityManagerFactory = buildEntityManagerFactory();
private static EntityManagerFactory buildEntityManagerFactory() {
try {
return Persistence.createEntityManagerFactory("MyPU");
} catch (Exception ex) {
throw new ExceptionInInitializerError(ex);
}
}
public static EntityManager getEntityManager() {
return entityManagerFactory.createEntityManager();
}
}
Thanks
You can use the two-parameter version of the createEntityManagerFactory() method. The second argument (the Map) can be used to pass properties including the credentials to the database. You can therefore pass in a map with keys javax.persistence.jdbc.user and javax.persistence.jdbc.password and appropriate values.
An example in the EclipseLink wiki demonstrates how to achieve this, although it uses classes provided by EclipseLink to achieve this:
import static org.eclipse.persistence.config.PersistenceUnitProperties.*;
...
Map properties = new HashMap();
// Ensure RESOURCE_LOCAL transactions is used.
properties.put(TRANSACTION_TYPE,
PersistenceUnitTransactionType.RESOURCE_LOCAL.name());
// Configure the internal EclipseLink connection pool
properties.put(JDBC_DRIVER, "oracle.jdbc.OracleDriver");
properties.put(JDBC_URL, "jdbc:oracle:thin:#localhost:1521:ORCL");
properties.put(JDBC_USER, "scott");
properties.put(JDBC_PASSWORD, "tiger");
// Configure logging. FINE ensures all SQL is shown
properties.put(LOGGING_LEVEL, "FINE");
properties.put(LOGGING_TIMESTAMP, "false");
properties.put(LOGGING_THREAD, "false");
properties.put(LOGGING_SESSION, "false");
// Ensure that no server-platform is configured
properties.put(TARGET_SERVER, TargetServer.None);
// Now the EntityManagerFactory can be instantiated for testing using:
Persistence.createEntityManagerFactory(unitName, properties);
Note that, it is also possible to do this via the EntityManagerFactory.createEntityManager() method, which accepts properties. However, if you read the EclipseLink auditing example carefully, you'll notice that a shared connection pool (whose properties are derived from persistence.xml) is also created, and that actual connection in use would depend on whether you are performing reads or writes.