h-thurow / simple-jndi Goto Github PK
View Code? Open in Web Editor NEWAccess property files via JNDI lookups. Get a DataSource from JNDI.
License: BSD 3-Clause "New" or "Revised" License
Access property files via JNDI lookups. Get a DataSource from JNDI.
License: BSD 3-Clause "New" or "Revised" License
The following CVEs were detected in the dependencies Simple-JNDI uses:
CVE-2022-41853
CVE-2021-29425
CVE-2020-15250
CVE-2017-5929
This is according to Maven Central here: https://mvnrepository.com/artifact/com.github.h-thurow/simple-jndi/0.23.0
They all need to be addressed at some point.
Simple-JNDI expects a parameter called "driver", but many other JNDI implementations, including TomCat, use driverClassName. Simple-JNDI should support that too, in order to allow drop-in of properties files.
In addition to searching a specific path on the filesystem, there should be a way to tell Simple-JNDI to search the classpath. That way configuration files can be dropped into the resources folder and Simple-JNDI can find them, no matter where they might be (e.g., in a JAR).
Hello!
At the moment my project looks like this:
<dependencies>
<dependency>
<groupId>com.github.h-thurow</groupId>
<artifactId>simple-jndi</artifactId>
<version>0.23.0</version>
</dependency>
<dependency>
<groupId>org.jboss.weld.se</groupId>
<artifactId>weld-se-core</artifactId>
<version>3.1.5.Final</version>
</dependency>
<dependency>
<groupId>javax.enterprise</groupId>
<artifactId>cdi-api</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
java.naming.factory.initial = org.osjava.sj.SimpleContextFactory
org.osjava.sj.jndi.shared = true
org.osjava.sj.root = config
@ApplicationScoped
public class Main
{
@Inject
private BeanManager beanManager;
public void init(@Observes ContainerInitialized event) throws NamingException
{
InitialContext ic = new InitialContext();
ic.bind("java:comp/env/BeanManager", beanManager);
BeanManager beanManager = (BeanManager) ic.lookup("java:comp/env/BeanManager");
System.out.println(beanManager.toString());
}
}
And it works as expected.
Now, instead of binding the beanManager
in the Main
class with ic.bind("java:comp/env/BeanManager", beanManager);
I would like to do that in an according properties file. Is this possible? I found the examples for DataSources
objects and the other Java types, but I'm a bit at loss at the moment. This is what I tried:
Using the following jndi.properties
:
java.naming.factory.initial = org.osjava.sj.SimpleContextFactory
org.osjava.sj.jndi.shared = true
org.osjava.sj.root = config
org.osjava.sj.space = java:comp/env
org.osjava.sj.delimiter=/
Should the env.properties
file be created unter the config
or under the config/java/comp
folder?
What should the env.properties
file look like?
BeanManager=? // I'm not sure how to get the injected object from above here - do I have to search for some kind of factory method within the weld library which I can state here?
BeanManager/type=javax.enterprise.inject.spi.BeanManager // If I understand correctly this is not supported
It would be great if you could give me some hints!
Hello,
I'm using Simple-JNDI in a Spring Boot application. It works as expected, however, I get exception like the following one on startup:
2021-07-23 15:24:03.010 ERROR 1980 --- [ main] org.osjava.sj.jndi.MemoryContext : MemoryContext#lookup("spring/mvc/pathmatch/use-suffix-pattern"): Invalid subcontext 'spring' in context '': MemoryContext{namesToObjects={}, subContexts={java:comp=MemoryContext{namesToObjects={}, subContexts={env=MemoryContext{namesToObjects={}, subContexts={string=MemoryContext{namesToObjects={}, subContexts={jndi-entries=MemoryContext{namesToObjects={hibernate_batch_fetchsize=#CHANGE_ME#, ur_miseendepot_gatewaytimeout=#CHANGE_ME#, binary_cache=#CHANGE_ME#, ur_miseendepot_encodagefichier=#CHANGE_ME#, ur_miseendepot_handlertimeout=#CHANGE_ME#, ur_miseendepot_thread_worker=#CHANGE_ME#, ur_miseendepot_thread_master=#CHANGE_ME#}, subContexts={}, env={org.osjava.sj.root=src/main/resources/jndi, org.osjava.sj.colon.replace=--, java.naming.factory.initial=org.osjava.sj.MemoryContextFactory, org.osjava.sj.delimiter=., jndi.syntax.direction=left_to_right, jndi.syntax.separator=/, org.osjava.sj.space=java:comp/env/string, org.osjava.sj.factory=org.osjava.sj.MemoryContextFactory}, nameParser=org.osjava.sj.jndi.SimpleNameParser@6f24ce45, nameInNamespace=java:comp/env/string/jndi-entries, nameLock=true}}, env={org.osjava.sj.root=src/main/resources/jndi, org.osjava.sj.colon.replace=--, java.naming.factory.initial=org.osjava.sj.MemoryContextFactory, org.osjava.sj.delimiter=., jndi.syntax.direction=left_to_right, jndi.syntax.separator=/, org.osjava.sj.space=java:comp/env/string, org.osjava.sj.factory=org.osjava.sj.MemoryContextFactory}, nameParser=org.osjava.sj.jndi.SimpleNameParser@e881e46, nameInNamespace=java:comp/env/string, nameLock=true}}, env={org.osjava.sj.root=src/main/resources/jndi, org.osjava.sj.colon.replace=--, java.naming.factory.initial=org.osjava.sj.MemoryContextFactory, org.osjava.sj.delimiter=., jndi.syntax.direction=left_to_right, jndi.syntax.separator=/, org.osjava.sj.space=java:comp/env/string, org.osjava.sj.factory=org.osjava.sj.MemoryContextFactory}, nameParser=org.osjava.sj.jndi.SimpleNameParser@657b3b, nameInNamespace=java:comp/env, nameLock=true}}, env={org.osjava.sj.root=src/main/resources/jndi, org.osjava.sj.colon.replace=--, java.naming.factory.initial=org.osjava.sj.MemoryContextFactory, org.osjava.sj.delimiter=., jndi.syntax.direction=left_to_right, jndi.syntax.separator=/, org.osjava.sj.space=java:comp/env/string, org.osjava.sj.factory=org.osjava.sj.MemoryContextFactory}, nameParser=org.osjava.sj.jndi.SimpleNameParser@2cea921a, nameInNamespace=java:comp, nameLock=true}}, env={org.osjava.sj.root=src/main/resources/jndi, org.osjava.sj.colon.replace=--, java.naming.factory.initial=org.osjava.sj.MemoryContextFactory, org.osjava.sj.delimiter=., jndi.syntax.direction=left_to_right, jndi.syntax.separator=/, org.osjava.sj.space=java:comp/env/string, org.osjava.sj.factory=org.osjava.sj.MemoryContextFactory}, nameParser=org.osjava.sj.jndi.SimpleNameParser@65753724, nameInNamespace=, nameLock=false}
Here I can see the JNDI entries I defined via the configuration files together with the configuration properties, which is fine, but there are also "Invalid subcontext spring". What am I supposed to do in order to get rid of these exceptions ?
Many thanls in advance.
Nicolas
Hi,
I am trying to load:
InitialContext ic = new InitialContext();
ic.lookup("java:jboss/datasources/my_ds");
But I get the error Invalid subcontext 'java:jboss' in context ''
Content of the src/test/resources/jndi.properties
file:
java.naming.factory.initial=org.osjava.sj.SimpleContextFactory
org.osjava.sj.root=src/test/resources/jndi
org.osjava.sj.delimiter=/
org.osjava.sj.space=java
org.osjava.sj.jndi.shared=true
Content of the src/test/resources/jndi/jboss/datasources.properties
file:
my_ds.type=javax.sql.DataSource
my_ds.driver=com.mysql.jdbc.Driver
my_ds.url=jdbc:mysql://localhost:3306/my_ds
my_ds.user=xxx
my_ds.password=xxx
What is wrong? Thanks!
Hi - I used Simple-JNDI in my project and built two JUnit 5 extensions for it, one to enable JNDI for an entire test class and another to enable JNDI for a single test method.
Would someone connected to Simple-JNDI be willing to review it? The pull request is here:
eeverman/andhow#537
The reason for creating these that it makes it so easy to use JNDI in a test and clean up after the test is done. For instance, here are the two tests that test the extension:
EnableJndiForThisTestMethodTest
EnableJndiForThisTestClassTest
I would be willing to contribute this to the Simple-JNDI project if you are interested.
Thank you,
Eric Everman
I'm trying to use Simple-JNDI with Tomcat 8 so I can use a different connection pool with Eclipselink (JPA) without having to configure the JNDI resource in Tomcat itself.
This answer on stackoverflow indicates that it was working with Tomcat 6 at least: https://stackoverflow.com/a/13936449/3375325
I'd like to use HikariCP instead of Eclipselink's internal connection pooling, so what I do is create a HikariDataSource
and try to bind it to a name, e.g. jdbc/OracleHikariDatasource
in my WebListener's contextInitialized
method. Unfortunately it already fails when calling new InitialContext()
with the following RuntimeException
:
java.lang.RuntimeException: Illegal node/branch clash. At branch value 'Property' an Object was found: [TEST, /logfiles/TEST/webapp]
at org.osjava.sj.loader.JndiLoader.createSubContexts(JndiLoader.java:310) ~[simple-jndi-0.14.0.jar:?]
at org.osjava.sj.loader.JndiLoader.jndiPut(JndiLoader.java:290) ~[simple-jndi-0.14.0.jar:?]
at org.osjava.sj.loader.JndiLoader.load(JndiLoader.java:223) ~[simple-jndi-0.14.0.jar:?]
at org.osjava.sj.loader.JndiLoader.loadDirectory(JndiLoader.java:125) ~[simple-jndi-0.14.0.jar:?]
at org.osjava.sj.loader.JndiLoader.loadDirectory(JndiLoader.java:82) ~[simple-jndi-0.14.0.jar:?]
at org.osjava.sj.SimpleJndi.loadRoot(SimpleJndi.java:78) ~[simple-jndi-0.14.0.jar:?]
at org.osjava.sj.SimpleContextFactory.getInitialContext(SimpleContextFactory.java:72) ~[simple-jndi-0.14.0.jar:?]
at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:684) ~[?:1.8.0_131]
at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:313) ~[?:1.8.0_131]
at javax.naming.InitialContext.init(InitialContext.java:244) ~[?:1.8.0_131]
at javax.naming.InitialContext.<init>(InitialContext.java:192) ~[?:1.8.0_131]
[...]
The mentioned directory is where log4j2 places the log files of my web application.
jndi.properties (placed under src/main/resources
)
java.naming.factory.initial=org.osjava.sj.SimpleContextFactory
org.osjava.sj.root=conf/
WebListener
@Override
public synchronized void contextInitialized(ServletContextEvent event) {
System.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.osjava.sj.SimpleContextFactory");
try {
Configuration config = new Configuration();
Context ctx = new InitialContext();
ctx.bind("jdbc/OracleHikariDatasource", config.getDataSource());
} catch (NamingException | SQLException | RuntimeException ex) {
log.error(ex.getMessage(), ex);
}
}
Is this supposed to work? Am I doing something wrong?
This documentation seems outdated:
https://github.com/h-thurow/Simple-JNDI/wiki/DataSource-Configuration-DBCP-2-and-Commons-Pool-2-(New-in-0.15.0)
When following this, I experienced an error in my logfile stating:
ERROR org.osjava.sj.loader.SJDataSourceConverter - Incomplete arguments provided <some more text>
There was no hint as of what exactly was missing. Checking https://github.com/h-thurow/Simple-JNDI/blob/master/src/main/java/org/osjava/sj/loader/convert/SJDataSourceConverter.java#L46 I found out that the properties file should contain these values:
type=javax.sql.DataSource
driver=org.mariadb.jdbc.Driver
url=jdbc:mariadb://localhost/testdb
user=user_name
password=password
So it might be nice to have the documentation updated.
I also noted there are IllegalArgumentExceptions thrown, but these must have been caught/hidden in the Simple-JNDI startup code. Please make them visible so it is more straightforward fixing issues.
Hi,
I think I found a bug, which is serious to my programmer team because it forces us to put our java projects into the same folders on each mache - so we cannot use our personal folders.
On my machine, the working directory (user.dir) is:
C:\Users\stefan\workspace_Projectname\wildfly\application\
org.osjava.sj.root=dataaccess\for_junit\ or:
org.osjava.sj.root=dataaccess/for_junit/ or:
I get the log message: Not found: C:\Users\stefan\workspace_Medion\wildfly\application\dataaccess\for_junit
Which is not true. The folder exists. But when I configure this as an absolute path, then it works. However that properties file in in the resource folder of the project. Therefore it shound not contain may personal name. I really want to use a relative folder.
When defining a datasource in a property file, or possibly any other supported resource, it would be great to be able to use system property substitution, e.g.
dataSource.serverName=${database.name}
This could be especially convenient for docker images or for quickly relocating the database server or also for passwords, which could be exported in the environment rather than being written in the file.
It would be great if the Simple JNDI jar included OSGi metadata.
Can you please add JndiLoader.SIMPLE_COLON_REPLACE to overwriteEnvironmentWithSystemProperties.
Maybe other props as well?
Thanks and Regards,
Mike
This is not an issue just a bit of help.
I have a need where i need to create a JNDI datasource dynamically and your project seemed ideal for me. However I think i got a bit confused and am unable to proceed.
It would be great if you could you give an example of programatically creating a context object for datasource lookup - say for DBCP2.
This should be accessed something like java:comp/env/jdbc/example_JNDI_DS
Thanks a ton in advance,
Simple-JNDI is writing a lot of debug level logs during the test of my application, is there a way to disable logging?
Thank you for your work.
I have seen that you have fixed the most CVE vulnerabilities with the commit 092fc77. Can you publish a new version of Simple-JNDI as Maven artifact?
By the way, Logback Classic 1.4.7 is affected by a new CVE vulnerability and has to be updated to version 1.4.12 or later.
For example i have set:
properties.setProperty("bootstrap.initialization.settingsource", "file");
So, if i try to lookup
ctx.ctx.lookup("prbootstrap/");
exception is rised. Seems to not to be bad to make these work the same as
ctx.ctx.lookup("prbootstrap");
How is the best way to hide password from datasource.properties file when using simple-jndi? Is there a way to use environment variables?
Since I wanted to create complex objects (DataSource) based on system properties (JDBC-URL, user, password with default values in case they are missing) I decided to populate SimpleJNDI programmatically, using this code:
DataSource ds = new MyDataSource();
InitialContext ictx = new InitialContext();
Context ctx = ictx.createSubcontext("jdbc");
ctx.bind("ds1", ds);
ctx = ctx.createSubcontext("NonJTA");
ctx.bind("ds2", ds);
On top of that I added Simple-JNDI to my test classpath and told Maven-Surefire to set the system property like so:
<dependency>
<groupId>com.github.h-thurow</groupId>
<artifactId>simple-jndi</artifactId>
<version>0.23.0</version>
<scope>test</scope>
</dependency>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<systemPropertyVariables>
<java.naming.factory.initial>org.osjava.sj.SimpleContextFactory</java.naming.factory.initial>
</systemPropertyVariables>
</configuration>
</plugin>
When running the application, I do get a warning message that no root is provided:
WARN org.osjava.sj.SimpleJndi - Mistakenly no root provided?
What should be provided, and why?
The suggestion is to add a line for "org.osjava.sj.jndi.ignoreClose" to SimpleJndi.overwriteEnvironmentWithSystemProperties()
method
If '#' is there as a property value as (in my case it was in a password for Database connection), then it is misunderstood as a start of the comment and getting escaped by the 'CustomProperties parser' of the library.
How to handle this ?
Hello, is it possible to configure a transaction manager to be accessible by JNDI?
I tried this, but didn't work, once each time InitialContext is created, it reads from the properties files and replace all previously binded resources:
InitialContext jndiCtx = new InitialContext();
jndiCtx.bind(JNDI_TRANSACTION_MANAGER, createTransactionManager());
jndiCtx.bind(JNDI_DATASOURCE_NAME, createDataSource());
Do you have any idea no I can have my TransactionManager
binded too?
Hi,
due to constraints of my application I need to access resources that are both on a java:app and java:comp subcontext. I can't seem to find, on the other hand, hints on the documentation to bind multiple contexts or to to create an aliased context.
Do you know if it's possible?
Would it be possible to have a properties file like this:
key=value
tmpdir=${user.home}/tmp
and access it at runtime with already-resolved values like `/home/user/tmp'?
I'm using Simple JNDI with a third party library that uses a Spring JndiTemplate to lookup objects from JNDI. The Spring JndiTemplate runs code like this for any JNDI operation (eg a lookup would execute
a JndiCallback
that ran ctx.lookup) an object:
public <T> T execute(JndiCallback<T> contextCallback) throws NamingException {
Context ctx = getContext();
try {
return contextCallback.doInContext(ctx);
}
finally {
releaseContext(ctx);
}
}
This is problematic as I have ~5 lookups for what is supposed to be the same connection pool and Spring causes a new Database Connection Pool to be created each time a lookup is run.
Would you approve of adding another property to disable removing contexts on close?
Hi,
what is wrong here?
A manual lookup in the unit test works. But when EclipseLink tries to lookup there is this exception...
Apr 27, 2019 12:14:53 AM org.osjava.sj.jndi.MemoryContext lookup
SEVERE: AbstractContext#lookup("java:comp/env/jdbc/MSDataDS"): Invalid subcontext 'java:comp' in context '':
AbstractContext{namesToObjects={},
subContexts={java:comp=AbstractContext{namesToObjects={},
subContexts={env=AbstractContext{namesToObjects={},
subContexts={jdbc=AbstractContext{namesToObjects={MSDataDS=org.h2.jdbcx.JdbcDataSource::::jdbc:h2:file:./target/msdata;AUTO_SERVER=TRUE::::sa},
subContexts={},
env={
org.osjava.sj.jndi.shared=true,
org.osjava.sj.root=src/test/jndi/,
java.naming.factory.initial=org.osjava.sj.MemoryContextFactory,
org.osjava.sj.delimiter=/,
jndi.syntax.separator=/,
jndi.syntax.direction=left_to_right,
org.osjava.sj.space=java:comp/env,
org.osjava.sj.factory=org.osjava.sj.MemoryContextFactory}, nameParser=org.osjava.sj.jndi.SimpleNameParser@1849db1a,
nameInNamespace=java:comp/env/jdbc,
nameLock=true}},
env={
org.osjava.sj.jndi.shared=true,
org.osjava.sj.root=src/test/jndi/,
java.naming.factory.initial=org.osjava.sj.MemoryContextFactory,
org.osjava.sj.delimiter=/,
jndi.syntax.separator=/,
jndi.syntax.direction=left_to_right,
org.osjava.sj.space=java:comp/env,
org.osjava.sj.factory=org.osjava.sj.MemoryContextFactory}, nameParser=org.osjava.sj.jndi.SimpleNameParser@69c79f09,
nameInNamespace=java:comp/env,
nameLock=true}},
env={
org.osjava.sj.jndi.shared=true,
org.osjava.sj.root=src/test/jndi/,
java.naming.factory.initial=org.osjava.sj.MemoryContextFactory,
org.osjava.sj.delimiter=/,
jndi.syntax.separator=/,
jndi.syntax.direction=left_to_right,
org.osjava.sj.space=java:comp/env,
org.osjava.sj.factory=org.osjava.sj.MemoryContextFactory}, nameParser=org.osjava.sj.jndi.SimpleNameParser@1ca25c47,
nameInNamespace=java:comp,
nameLock=true}},
env={
java.naming.factory.initial=org.osjava.sj.MemoryContextFactory,
org.osjava.sj.delimiter=/,
jndi.syntax.direction=left_to_right,
org.osjava.sj.jndi.ignoreClose=false,
org.osjava.sj.space=java:comp/env,
org.osjava.sj.root=src/test/jndi/,
org.osjava.sj.factory=org.osjava.sj.MemoryContextFactory,
jndi.syntax.separator=/,
org.osjava.sj.jndi.shared=true},
nameParser=org.osjava.sj.jndi.SimpleNameParser@5fcacc0,
nameInNamespace=,
nameLock=false}
[EL Severe]: 2019-04-27 00:14:53.576--ServerSession(1523084197)--Exception [EclipseLink-7060] (Eclipse Persistence Services - 2.7.4.v20190115-ad5b7c6b2a): org.eclipse.persistence.exceptions.ValidationException
Exception Description: Cannot acquire data source [java:comp/env/jdbc/MSDataDS].
Internal Exception: javax.naming.NamingException
When moving the application, the root folder of Simple-JNDI most of the times needs to be relocated, so I believe it would be good to make it sufficient to specify the value via system properties, while now it's also mandatory to have it in jndi.properties.
Currently, I can specify pretty much all configuration values that would need to be set in jndi.properties via system properties, with the exception of the root path. In fact, I have a jndi.properties file which only contains the root, with a dummy value that I will be later overwriting via system property.
Still, a root declaration in jndi.properties is mandatory because, even if the code already supports that the root is overwritten via system property in SimpleJNDI.overwriteEnvironmentWithSystemProperties()
, if the root is not specified in the properties file the code will fail before reaching the above method when the SimpleJndiContextFactory is initialized in line 73, because contextsByRoot is a concurrent hashmap that does not allow a null key and throws a NPE:
`final String root = (String) environment.get(SimpleJndi.ROOT);`
`final Context ctx = contextsByRoot.get(root);`
`if (ctx != null) {`
The code after the map lookup seems to be able to deal with a null Context, so a change like the following should work:
` final String root = (String) environment.get(SimpleJndi.ROOT);`
` final Context ctx = root != null? contextsByRoot.get(root) : null;`
`if (ctx != null) {`
If you are OK with the idea I can raise a pull request.
Edit: fix typo and formatting
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.