1

I created with Springboot a JAR application. I launch this JAR application under Tomcat server.

One asks me to use JNDI to retrieve datasource stored in the Tomcat context.xml, saying it's easy.

I try to do this with this following code.

Context initContext;
        try {
            initContext = new InitialContext();
            Context envContext = (Context) initContext.lookup("java:comp/env");
            DataSource ds = (DataSource) envContext.lookup("jdbc/mydatabase");
        } catch (NamingException e) {
            System.out.println("ERROR!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
            e.printStackTrace();
            System.out.println("ERROR!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
        }

But it does not work.

I obtain this error :

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

Is it a simple mean to overcome this problem ?

Or with my JAR standalone application, it is still absolutely impossible to overcome this problem, like the precedent post Tomcat JNDI + Standalone Java informs ?

I see many posts, many docs but it remains unclear for me.

Thanks for your help, your sharing.

Thomas

  • Are you using embedded Tomcat ? – Kedar Joshi Dec 31 '20 at 16:40
  • Thanks a lot Kedar. I am not using embedded Tomcat. I make a "mvn clean package" to create my JAR and then i have to put via MobaXTerm on an existing Tomcat server (anywhere on this existing server) and finally i run in this existing Tomcat server the jar via the command "jar -jar myJar". – Thomas Campos Dec 31 '20 at 17:14
  • 1
    If you are using `java -jar myJar` then you are using embedded Tomcat. In that case, you may not have a JNDI datasource. – Kedar Joshi Jan 02 '21 at 14:37
  • Thanks a lot Kedar. Your analysis help me a lot. I have bookmarked this post, i hope that it tags this post as answered. Just a little question : if you know a good documentation explaining all these facts, i am very interested. A Big Thanks to You and have a nice day and week. – Thomas Campos Jan 03 '21 at 22:44
  • I see also this old post that seems to be interesting : https://stackoverflow.com/questions/24941829/how-to-create-jndi-context-in-spring-boot-with-embedded-tomcat-container. But, thanks to your help Kedar, i am in the right way. – Thomas Campos Jan 03 '21 at 22:46

2 Answers2

0

Kedar brings me an answer. I make a summary of the Kedar answer :

  • when running your JAR application with the jar command line, i am using embedded Tomcat
  • when i use embedded Tomcat, it's possible that i have not access to my JNDI datasource That's the reason why my JNDI does not work. I will try to see this post to configure my application in order to try tu use JNDI : How to create JNDI context in Spring Boot with Embedded Tomcat Container But, now, thanks to Kedar, i understand why my JNDI code does not work. I will see the other post to see how configure to use anyway JNDI if possible. Thanks Kedar.
  • 1
    Kedar, i want to tag your answer as "Answer" but i can't since you write as comment. But what you write answers to my question. I have to look in this direction. You indicate me the good direction. Thanks Kedar. – Thomas Campos Jan 04 '21 at 09:04
0

Sorry for the delay to give the answer.

Thanks to Kedar that indicates me that JNDI does not work with a JAR, i try to :

  • read on the Tomcat server the context.xml file
  • extract from this context.xml file the XML element containing all the properties concerning the database
  • construct a DataSource object from this database properties

Thanks also to MKyong with this tutorial : https://mkyong.com/java/how-to-read-xml-file-in-java-dom-parser/

Here is my working code under SpringBoot :

@Configuration
public class ApplicationConfiguration {

/**
 * Absolute path of the configuration file named context.xml on any Tomcat Server (DEV, TEST, PROD).
 */
private final String CONTEXT_XML_PATH_ON_SERVER = "/opt/tomcat/apache-tomcat-version/conf/context.xml";

@Bean
@Primary
public DataSource dataSource() {
    try {
        Element datasourceElement = getDatasourceElementInTomcatContextXml();
        return DataSourceBuilder
                .create()
                .username(datasourceElement.getAttribute("username"))
                .password(datasourceElement.getAttribute("password"))
                .url(datasourceElement.getAttribute("url"))
                .driverClassName(datasourceElement.getAttribute("driverClassName"))
                .build();
    } catch (ParserConfigurationException e) {
        e.printStackTrace();
    } catch (SAXException | IOException e) {
        e.printStackTrace();
    }
    return null;
}

private Element getDatasourceElementInTomcatContextXml() throws ParserConfigurationException, SAXException, IOException {
    File contextXmlFile = new File(CONTEXT_XML_PATH_ON_SERVER);
    DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
    DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
    Document doc = dBuilder.parse(contextXmlFile);
    //optional, but recommended
    //read this - http://stackoverflow.com/questions/13786607/normalization-in-dom-parsing-with-java-how-does-it-work
    doc.getDocumentElement().normalize();
    NodeList resourceElementList = doc.getElementsByTagName("Resource");
    Node nNode = resourceElementList.item(0);
    Element eElement = (Element) nNode;
    return eElement;
}

}

Thanks Kedar and MKyong.

Thomas