GithubHelp home page GithubHelp logo

sbearcsiro / simple-jndi Goto Github PK

View Code? Open in Web Editor NEW

This project forked from h-thurow/simple-jndi

0.0 1.0 0.0 1.17 MB

Access property files via JNDI lookups. Get a DataSource from JNDI.

License: BSD 3-Clause "New" or "Revised" License

Java 100.00%

simple-jndi's Introduction

Simple-JNDI

Simple-JNDI is intended to solve two problems. The first is that of finding a container independent way of opening a database connection, the second is to access application configurations easily from anywhere in your application.

Unit tests or prototype code often need to emulate the environment within which the code is expected to run. A very common one is to get an object of type javax.sql.DataSource from JNDI so a java.sql.Connection to your database of choice may be opened.

This JNDI implementation is entirely memory based, so no server instances are started. The structure of a root directory serves as a model for the contexts structure. The contexts get populated with Objects defined by .properties files, XML files or Windows-style .ini files. Of course you can bind Objects programmatically to contexts too.

Download

<dependency>
    <groupId>com.github.h-thurow</groupId>
    <artifactId>simple-jndi</artifactId>
    <version>0.15.0</version>
</dependency>

or download from here.

Installing Simple-JNDI

After download, installing Simple-JNDI is as simple as adding the simple-jndi jar to your classpath. Some of the features do however need additional dependencies. To get connection-pooling you will need commons-dbcp, commons-dbcp2 or HikariCP.

Setting up Simple-JNDI

This is where all the work goes in a Simple-JNDI installation. Firstly you need a jndi.properties file, which somehow needs to go into your classpath. This jndi.properties needs two mandatory values:

java.naming.factory.initial=org.osjava.sj.SimpleContextFactory

This property, java.naming.factory.initial, is a part of the jndi specification.

The second required parameter, org.osjava.sj.root, is the location of your simple-jndi root, which is the location in which simple-jndi looks for values when code asks for them. The following code block details a few examples with explanatory comments.

# absolute directory, using the default file protocol
org.osjava.sj.root=/home/hen/gj/simple-jndi/config/
# relative directory, using the default file protocol
org.osjava.sj.root=config/
# NEW in 0.13.0: Specify a list of files and/or directories. Separate them by the platform specific path separator.
org.osjava.sj.root=file1.cfg:directory1/file.properties:directory2

See also Load property files with any extension from any location.

Declaratively create your contexts and context objects

Simple-JNDI stores values in multiple .properties, xml or ini files. The files are located under a root directory as specified with the org.osjava.sj.root property.

Directory names and file names become part of the lookup key. Each delimited tree-node becomes a JNDI Context, while the leaves are implementations. The only exceptions are pseudo sub-values, which you will see with DataSources.

The easiest way to understand is to consider an example. Imagine a file-structure looking like,

    config/application1/users.properties

in which the file looks like:

    admin=fred
    quantity=5
    enabled=true

The following pieces of Java are all legal ways in which to get values from Simple-JNDI. They assume that you set org.osjava.sj.root=config and that you instantiated ctxt by executing 'InitialContext ctxt = new InitialContext();'.

  • String value = (String) ctxt.lookup("application1.users.admin")
  • String value = (String) ctxt.lookup("application1.users.quantity")
  • String value = (String) ctxt.lookup("application1.users.enabled")

Further information.

Lookup typed properties, not only Strings

In the above example it would be favourable to lookup "quantity" as Integer and "enabled" as Boolean. To achieve this you can type your properties:

    quantity=5
    quantity.type=java.lang.Integer
    enabled=true
    enabled.type=java.lang.Boolean

Thereafter you can call typed properties:

    Integer value = (Integer) ctxt.lookup("application1.users.quantity");
    Boolean value = (Boolean) ctxt.lookup("application1.users.enabled");

The following types are supported: Byte, Short, Integer, Long, Float, Double, Character.

Also supported are Maps (0.16.0):

    city.type = java.util.Map
    city.citizens = 3.520.031
    city.name = Berlin

Now you can lookup a Map:

    Map myMap = (Map) ctx.lookup("city");
    assertEquals("3.520.031", myMap.get("citizens"));

For further map examples see here.

Note that you have to write "quantity/type=java.lang.Integer" and "enabled/type=java.lang.Boolean" when setting "org.osjava.sj.delimiter=/" unless you follow this description. And as you might anticipate already: "type" is a reserved word with Simple-JNDI.

See also
A more elegant way to lookup typed properties (New in 0.14.0)
Load self-defined types as Beans (New in 0.15.0)

Lookup pathes with "/" as context separator instead of "."

So far we used "." as context separator in lookup pathes like in

ctxt.lookup("application1.users.enabled");

But more usual in JNDI world are lookup pathes like

ctxt.lookup("application1/users/enabled");

This is what org.osjava.sj.delimiter is for. If not specified, then a '.' is chosen. To use "/" as separator in lookup pathes set

org.osjava.sj.delimiter=/

Note that you can not mix up different separators in property names and lookup pathes. When setting "org.osjava.sj.delimiter=/" and using namespaced property names you can not declare "a.b.c=123". You have to declare "a/b/c=123". See also ENC problem.

See also Use slash separated lookup pathes with dot separated property names (New in 0.14.0)

DataSources

The most popular object to get from JNDI is an object of type javax.sql.DataSource, allowing the developer to obtain JDBC connections to databases. Simple-JNDI supports this out of the box. See

DataSource Configuration DBCP 2 and Commons Pool 2 (New in 0.15.0)
DataSource Configuration HikariCP (New in 0.15.0)
DataSource Configuration (commons dbcp 1)
Usage with Spring - Inject a DataSource into beans

Shared or unshared context?

Setting org.osjava.sj.jndi.shared=true will put the in-memory JNDI implementation into a mode whereby all InitialContexts share the same memory. By default this is not set, so every new InitialContext() call will provide an independent InitialContext that does not share its memory with the other contexts. When binding an object to one of these contexts by calling Context.bind() this object is not visible in the other contexts. This could be not what you want when using a DataSource or a connection pool because everytime you call new InitialContext() in your application a new DataSource or a new connection pool is created.

Dealing with "java:comp/env" (Environment Naming Context, ENC) while loading

Set the org.osjava.sj.space property. Whatever the property is set to will be automatically prepended to every value loaded into the system. Thus org.osjava.sj.space=java:comp/env simulates the JNDI environment of Tomcat. The org.osjava.sj.space property is not subject to delimiter parsing, so even when org.osjava.sj.delimiter is set to ".", you have to lookup "java:comp/env", not "java:comp.env". See also ENC problem.

Another way to achieve a similar result is putting a default.properties directly under your root. In this file declare all your context objects that should reside under "java:comp/env" by prefixing all properties with "java:comp/env", e. g. "java:comp/env/my/size=186". This way you can set some context objects in "java:comp/env" and other objects in a different name space.

You could also put a file named "java:comp.properties" in your root directory or name a directory under your root directory "java:comp". But Windows does not like having a : in a filename, so to deal with the : you can use the org.osjava.sj.colon.replace property. If, for example, you choose to replace a : with -- (ie org.osjava.sj.colon.replace=--), then you will need a file named java--comp.properties, or a directory named java--comp containing a file "env.properties".

Context.close() and Context.destroySubcontext()

Either methods will recursively destroy every context and dereference all contained objects. So when writing JUnit tests, it is good practice to call close() in tearDown() and reinitialize the JNDI environment in setUp() by calling new InitialContext(). But do not forget to close your datasources by yourself.

See also

Change log

References

Creating Integration Tests with JNDI

Explanatory note

This project is based on old https://github.com/hen/osjava/tree/master/simple-jndi .

  • Several bugs fixed and many new tests added. See Failed Tests in 0.11.4.1
  • Changed the way contexts are shared, because of ContextNotEmptyException with type=javax.sql.DataSource and Beans. In shared mode subcontexts and bound objects are now managed per context and not in a single static map for the same reason.
  • Tests ported to JUnit 4.
  • Maven 2/3 support.
  • Support for additional basic datatypes (Byte, Short, Integer, Long, Float, Double, Character) in type declaration.

simple-jndi's People

Contributors

h-thurow avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.