4

I have a Java project, which connects to Oracle 12c database. Previously the ojdbc jar (and all other dependencies) had to be on the classpath for the jar to be able to run. However this is intended to be a standalone app, so I wanted to setup a build process which in the end spits out a single jar with all dependencies included. I made the following steps:

  • Converted the project to a Maven project
  • Setup dependencies like Log4j as Maven dependencies
  • Following this guide, I managed to include ojdbc as dependency
  • Setup maven-assembly-plugin to generate a runnable jar like this:
<plugin>
    <artifactId>maven-assembly-plugin</artifactId>
    <configuration>
        <archive>
            <manifest>
                <mainClass>fully.qualified.path.to.Main</mainClass>
            </manifest>
            <manifestEntries>
                <Built-On>${maven.build.timestamp} UTC</Built-On>
                <ModuleName>${project.name}</ModuleName>
                <ModuleVersion>${project.version}</ModuleVersion>
            </manifestEntries>
            <manifestSections>
                <manifestSection>
                    <name>Release section</name>
                    <manifestEntries>
                        <BaseVersion>${baseversion}</BaseVersion>
                        <BuildNumber>${buildnumber}</BuildNumber>
                        <GITRevision>${gitrevision}</GITRevision>
                    </manifestEntries>
                </manifestSection>
            </manifestSections>
        </archive>
        <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
        </descriptorRefs>
    </configuration>
    <executions>
        <execution>
            <id>make-assembly</id>
            <phase>package</phase>
            <goals>
                <goal>single</goal>
            </goals>
        </execution>
    </executions>
</plugin>

The resulting jar includes most of the dependencies in form of class files, e.g. there is an 'org/apache/log4j' folder in the root of the jar with Log4j class files. The problem is that the ojdbc (com/oracle/jdbc) is not there, and I'm getting ClassNotFoundExceptions runtime. I checked and the ojdbc jar is present under my .m2 folder in the correct path.

Is there any way to include the ojdbc dependencies, either as a jar or as class files, in my runnable jar?

EDIT: Based on Essex Boy's comment, I used the shade plugin like so:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-shade-plugin</artifactId>
    <version>3.2.1</version>
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <goal>shade</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <minimizeJar>true</minimizeJar>
        <transformers>
            <transformer
                implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                <manifestEntries>
                    <Main-Class>fully.qualified.path.to.Main</Main-Class>
                    <Built-On>${maven.build.timestamp} UTC</Built-On>
                    <ModuleName>${project.name}</ModuleName>
                    <ModuleVersion>${project.version}</ModuleVersion>
                    <BaseVersion>${baseversion}</BaseVersion>
                    <BuildNumber>${buildnumber}</BuildNumber>
                    <GITRevision>${gitrevision}</GITRevision>
                </manifestEntries>
            </transformer>
        </transformers>
    </configuration>
</plugin>

With this I get a similar jar, with most dependencies, but ojdbc is still excluded. I tried to add an artifactSet tag, and include 'com.oracle.jdbc:ojdbc8' explicitly, but still it is not added. The only upside is that with the minimizeJar option I get a smaller jar with only the actual dependencies included.

Gábor Major
  • 444
  • 2
  • 8
  • 23
  • use the [shade plugin](https://maven.apache.org/plugins/maven-shade-plugin/), much easier, look at this [answer](https://stackoverflow.com/questions/54868754/maven-no-main-manifest-attribute/54869142#54869142) – Essex Boy Apr 24 '19 at 08:54
  • @EssexBoy I added the plugin, check the edited question. – Gábor Major Apr 24 '19 at 09:31
  • @Abra sure, but is there really no way to include ojdbc as a dependency? I always have to have the ojdbc jar separately, and include it in the classpath? – Gábor Major Apr 24 '19 at 09:32
  • @Abra What exactly is 'old-fashioned' about that? – user207421 Apr 24 '19 at 09:46
  • Did you ever find an answer? I have the same problem. When I run my .jar built with Maven Shade I get "java.sql.SQLException: No suitable driver found jdbc:oracle" but it runs without error in Eclipse. If I inspect the .jar I can see that the Oracle .jars have been included. I do get a warning in Maven when I compile [WARNING] example-1.0-SNAPSHOT.jar, ojdbc10-19.3.0.0.jar, ons-19.3.0.0.jar, oraclepki-19.3.0.0.jar, osdt_cert-19.3.0.0.jar, osdt_core-19.3.0.0.jar, simplefan-19.3.0.0.jar, ucp-19.3.0.0.jar define 1 overlapping resources: [WARNING] - META-INF/MANIFEST.MF which may be related. – jrandj Mar 25 '20 at 09:55
  • @Abra That's hardly an answer to my question. The whole of Java predates Maven, and Maven can certainly create Class-Path entries in the manifest, which is still the correct solution here. – user207421 Jun 04 '21 at 04:13

1 Answers1

-1

Found the answer. You need to set this. Class.forName("oracle.jdbc.driver.OracleDriver")

Cuong Dang
  • 39
  • 5
  • That (a) has been unnecessary since 2007 and (b) won't work if the OJDBC .jar file isn't available. – user207421 Jun 04 '21 at 01:18
  • I ran into the exact same problem with OP. Ran just fine with an IDE but when I tried to build a fat jar, it failed, without the `Class.forName`. Then I looked around a lot and came upon some sort of old resource that said it was necessary. I put in the `Class.forName`, built a fat jar, and voila, it worked. Didn't change anything else and didn't have the ojdbc8.jar available. You could try it before dismissing my solution. – Cuong Dang Jun 04 '21 at 04:17
  • I don't need to try it. I already know. I've written JDBC drivers. If the OP's problem is that he can't bundle the OJDBC JAR file correctly, adding a `Class.forName()` line won't fix it: it will just lead to a `ClassNotFoundException`; and if he does bundle the JAR file correctly, i.e. via naming it in the manifest `Class-Path` attribute, or building a fat JAR file *correctly,* which isn't quite as simple as it may sound, he doesn't need this line and he doesn't have a question to answer. The `Class.forName()` requirement was removed in JDBC 4 in 2007. – user207421 Jun 04 '21 at 04:36