1

I've created a JSP server (tomcat) and have linked it to my Eclipse IDE. I've also created a PostgreSQL server and am trying to figure out how to connect to it via my JSP server.

Here is how my JSP file looks like:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
    <%@ page import="helloWorldJSP.Test" %>
    <%@ page import="helloWorldJSP.SQLTest" %>
</head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<%
    //Test testThing = new Test();  
    //out.println( testThing.caps("thing") );
    SQLTest test = new SQLTest();
    System.out.println("FINISH");
%>


</body>
</html>

I've tested it and it works, so I don't think the error lies within this page.

Here's the code to my SQLTest class:

package helloWorldJSP;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;

public class SQLTest 
{
    public SQLTest() 
    {
        Connection conn = null;
        System.out.println("STARTING");

        try 
        {

            String url = "jdbc:postgresql://localhost:5432/deama_db";
            String user = "deama1295";
            String password = "1295";

            conn = DriverManager.getConnection(url, user, password);
            if (conn != null) 
            {
                System.out.println("Connected to the database postgres");
            }
        }
        catch (SQLException ex) 
        {
            System.out.println("An error occurred. Maybe user/password is invalid");
            ex.printStackTrace();
        }
    }
}

In my tomcat server lib folder I've looked for the JDBC driver and it is there. I am running Ubuntu-18.10-desktop-amd64 from a virtualBox virtual machine.

I've tried changing the database and username to "postgres" (the default I believe?) but that didn't change my error (I'm pretty sure I set the password of postgres to 1295).

Here is the full error message:

java.sql.SQLException: No suitable driver found for jdbc:postgresql://localhost/deama_db
    at java.sql.DriverManager.getConnection(DriverManager.java:689)
    at java.sql.DriverManager.getConnection(DriverManager.java:208)
    at helloWorldJSP.SQLTest.<init>(SQLTest.java:26)
    at org.apache.jsp.NewFile_jsp._jspService(NewFile_jsp.java:127)
    at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
    at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:476)
    at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:386)
    at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:330)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:493)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:650)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:800)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:806)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1498)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:748)
  • you need to place the JDBC driver in WAR's /WEB-INF/lib and perform .. Class.forName("com.example.jdbc.Driver"); .. in your code before the first DriverManager#getConnection() call – ZhaoGang Dec 27 '18 at 01:48
  • 1
    @ZhaoGang Only the first part. Haven't needed `Class.forName` since JDBC 4 (Java 6). – Elliott Frisch Dec 27 '18 at 01:53

2 Answers2

0

You are probably missing a reference to PostgreSQL JDBC Driver in your. This might be a relevant answer (for Android OS).

Since you are using ASP.NET, you might will need to install Postgres via this nuget.

You most likely need to add Postgres into your java application, quoting:

You need to add the PostgreSQL JDBC Driver in your project as mentioned in Mvnrepository.

Gradle:

// http://mvnrepository.com/artifact/postgresql/postgresql
compile group: 'postgresql', name: 'postgresql', version: '9.0-801.jdbc4'

Maven:

<dependency>
    <groupId>postgresql</groupId>
    <artifactId>postgresql</artifactId>
    <version>9.0-801.jdbc4</version>
</dependency>

You can also download the JAR and import to your project manually.

Menelaos Kotsollaris
  • 5,776
  • 9
  • 54
  • 68
  • When I linked the apache tomcat server with my Eclipse IDE it added it to my library, I can see a reference to the jdbc driver.jar file from tomcat's /lib folder in my libraries tab for my project; it still doesn't work. – dragonh pame Dec 29 '18 at 18:36
0

According to the Tomcat 8 documentation on JNDI Datasources, the default behavior for loading drivers using DriverManager is to read them from the Apache-Tomcat-Home/lib folder. Otherwise, you will have to register the driver(s) explicitly. It basically has to do with Tomcat's class loading mechanism. Here is an excerpt from the documentation:

The JRE Memory Leak Prevention Listener that is included with Apache Tomcat solves this by triggering the drivers scan during Tomcat startup. This is enabled by default. It means that only libraries visible to the listener such as the ones in $CATALINA_BASE/lib will be scanned for database drivers. If you are considering disabling this feature, note that the scan would be triggered by the first web application that is using JDBC, leading to failures when this web application is reloaded and for other web applications that rely on this feature.

Thus, the web applications that have database drivers in their WEB-INF/lib directory cannot rely on the service provider mechanism and should register the drivers explicitly. This behavior should apply to newer versions of Tomcat.

The key here is the JRE Memory Leak Prevention Listener behavior when looking up database drivers using DriverManager. This listener, according to the documentation:

provides work-arounds for known places where the Java Runtime environment uses the context class loader to load a singleton as this will cause a memory leak if a web application class loader happens to be the context class loader at the time. The work-around is to initialise these singletons when this listener starts as Tomcat's common class loader is the context class loader at that time.

But in your case as it my in case, I was able to re-produced the error, the web application class loader was different than the context class loader and hence it didn't find the driver. So the solution is to configure the listener to disable DriverManager protection - the default value it set to true. You do this by setting the driverManagerProtection property value to false in the Apache-Tomcat-Home/conf/server.xml file:

<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" driverManagerProtection="false"/>

That said, I don't believe the DriverManager is the correct way to instantiate database connections in a web server; Database connections are expensive. I would recommend to use DataSource, which pools connections and hence improves performance. See provided documentation link for examples.

I do believe, however, that every technology has it's place. So... I'll leave it up to you to decide what works in your case. But at least, you have your answer.

Jose Henriquez
  • 356
  • 2
  • 7
  • But the postgress driver hast ot be there in the first place. – Juan Dec 27 '18 at 03:19
  • @dragonhpame - after further reading the documentation, the `/lib` folder is correct folder to put the database drivers. However, all their examples are doing a JNDI lookup instead of using `DriverManager`. I want to run some test on my end. What version of Apache Tomcat are you running? - Thanks. – Jose Henriquez Dec 28 '18 at 05:33
  • @JoseHenriquez - I'm running tomcat 8.5 – dragonh pame Dec 29 '18 at 01:18