Skip to main content

Patching a Maven library with your custom class.

Sometimes you use a library that has a bug. Or maybe it doesn’t has a bug but you want to change something. Of course if it is an open source you can get the sources… build them … with your change and so on. However this first takes a lot of time and second you need the sources.
What you usually want .. is to just replace one class.. or few classes with something custom… maybe add a line .. or remove a line and so on.
Yesterday… I had an issue with jboss-logging. The version I was using was 3.2.0Beta1 and it turns out that using this version and log4j2 2.0 final basically meant that no log is send to log4j2. The reason was a null pointer exception that was catched in jboss logging class called Log4j2Logger. The bug I submitted is here https://issues.jboss.org/browse/JBLOGGING-107 and it was fixed at the same day. However I will use it as an example since I didn’t knew when this will be fixed.. and I didn’t want to wait till it is fixed.
So I was thinking what I want.. to take the jboss-logging  jar  and replace the file called Log4j2Logger. Basically as you can see in the bug I wanted to replace line 54 to be :
instead of :
this.logger.log(null, loggerClassName, translatedLevel,
parameters == null || parameters.length == 0 ? this.messageFactory.newMessage(message) :
this.messageFactory.newMessage(String.valueOf(message), parameters),
thrown);
to become :
this.logger.log(translatedLevel, parameters == null || parameters.length == 0 ? this.messageFactory.newMessage(message) : this.messageFactory.newMessage(String.valueOf(message), parameters),

And that’s it. Of course I didn’t wanted to do this manually with zip Усмивка but to use maven as well.

So what I did:

1) I created a new maven project and added as dependency the jboss-logging.
2) I set the new project groupid and artifactid as the ones in the dependancy.
I set the version to be something like “3.2.0.Beta1-log4j2-npe-fix” so I added –log4j2-npe-fix
3) I used a plugin that takes the original version, unpacks the original jar in target WITHOUT the class I want to patch in this case Log4j2Logger.class and added my own implementation in the sources of my project.
4) And well thats all... ones I build.. my patched class will go in target.. and the original classes except the class I want to patch will also go in target and voala.. I will have a library which is patched.
The full pom.xml looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>

    <groupId>org.jboss.logging</groupId>
    <artifactId>jboss-logging</artifactId>
    <version>3.2.0.Beta1-log4j2-npe-fix</version>
    <dependencies>
        <dependency>
            <groupId>org.jboss.logging</groupId>
            <artifactId>jboss-logging</artifactId>
            <version>3.2.0.Beta1</version>
            <type>jar</type>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <executions>
                    <execution>
                        <id>unpack</id>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>unpack</goal>
                        </goals>
                        <configuration>
                            <artifactItems>
                                <artifactItem>
                                    <groupId>org.jboss.logging</groupId>
                                    <artifactId>jboss-logging</artifactId>
                                    <version>3.2.0.Beta1</version>
                                    <type>jar</type>
                                    <overWrite>true</overWrite>
                                    <outputDirectory>${project.build.directory}/classes</outputDirectory>
                                    <excludes>
                                        **/Log4j2Logger.class
                                    </excludes>
                                </artifactItem>
                            </artifactItems>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>
 

and that’s it.. the only thing left is to update my project to use my version 3.2.0.Beta1-log4j2-npe-fix instead of the original 3.2.0.Beta1.



I hope this will help to someone to save time.
  
 

Comments

Popular Posts

Use Multiple JVM versions on Mac OS and Linux

Linux Download multiple Java versions and put them into /opt/ If you already have some JDK from ubuntu repo or etc not a big deal, just fix the paths bellow Register them as alternatives sudo update-alternatives --install /usr/bin/java java /opt/java-8-oracle/bin/java 1081 sudo update-alternatives --install /usr/bin/java java /opt/sap-machine-jdk-11.0.3/bin/java 1080 Edit your ~/.bashrc file alias java11='sudo update-alternatives --set java /opt/sapmachine-jdk-11.0.3/bin/java;export JAVA_HOME=/opt/sapmachine-jdk-11.0.3/' alias java8='sudo update-alternatives --set java /opt/java-8-oracle/bin/java;export JAVA_HOME=/usr/lib/java-8-oracle/' SAVE and start a new bash terminal execute java8 to use java8 java11 to use java11 the latest version you have set stays as system wide, but the JAVA_HOME is not :( you can put java8 or java11 as a last line in the bashrc but since it is sudo it will always require password when start and is not gr...

JavaEE 5 (JSF + JPA + EJB3) using Eclipse

Today I will show you how to create Enterprise Application using Java EE 5 and GlassFish. I will use - Eclipse 3.5 + WTP - GlassFish v. 2.1 - JSF Mojarra implementation. - EJB 3.0. - JPA Toplink essentials implementation. - MySQL No NetBeans or JDeveloper magic involved :) The prerequirement is: Add datasource in glassfish. Read this how you can make this here: http://gochev.blogspot.com/2009/10/creating-datasource-in-glassfish-v-21.html 1) First you need to add glassfish in your eclipse. - Go to Servers View - Right Click, New - Choose GlassFish v 2.1 if you dont have glassfish click on Download additional adapters link choose glassfish wait and restart eclipse. Than try again. 2) Create the database CREATE TABLE ` lesson ` . ` USERS ` ( ` id ` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, ` username ` VARCHAR ( 45 ) NOT NULL , ` password ` VARCHAR ( 45 ) NOT NULL , ` name ` VARCHAR ( 45 ) NOT NULL , PRIMARY KEY ( ` id ` ) ) ENGINE = InnoDB...