Skip to main content

JSF, RichFaces, Spring, Hibernate – lets make development easy.

The goal of this article is to show you how you can use Hibernate, Spring and JSF 1.2 in the most easiest way.

Used technologies :

  • maven 2
  • JSF 1.2 (MyFaces)
  • Spring 2.5.6
  • Hibernate 3.2.1.GA

In the example I will use mysql just for the configuration. You can use whatever you want. The goal that we want is to use Spring for management of transactions and as IoC container. The beast way for us is to make everything spring beans. In typical application we will have Services, DAOs, Entity objects and JSF managed beans. We will make all of them spring beans and use @Autowired annotation (included in Spring). We will use GenericDAO implementation which is explained in this article: http://gochev.blogspot.com/2009/08/hibernate-generic-dao.html.

First lets create a maven 2 project and add replace update it’s pom.xml to looks like this, note that the pom is big we will explain important sections after the whole content.

<?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/maven-v4_0_0.xsd">

      <modelVersion>4.0.0</modelVersion>

      <groupId>myproject-web</groupId>

      <artifactId>myproject-web</artifactId>

      <packaging>war</packaging>

      <version>0.0.1-SNAPSHOT</version>

      <name>A custom project using myfaces</name>

      <url>http://www.myorganization.org</url>

 

      <build>

            <finalName>myproject-web</finalName>

            <plugins>

                  <plugin>

                        <!--This plugin allows to run the example using mvn jetty:run -->

                        <groupId>org.mortbay.jetty</groupId>

                        <artifactId>maven-jetty-plugin</artifactId>

                        <version>6.1.8</version>

                        <configuration>

                             <scanIntervalSeconds>10</scanIntervalSeconds>

                        </configuration>

                  </plugin>

                  <plugin>

                        <artifactId>maven-compiler-plugin</artifactId>

                        <configuration>

                              <source>1.5</source>

                              <target>1.5</target>

                        </configuration>

                  </plugin>

 

                  <plugin>

                        <artifactId>maven-eclipse-plugin</artifactId>

                        <configuration>

                              <wtpversion>2.0</wtpversion>

                             <wtpapplicationxml>true</wtpapplicationxml>

                              <wtpmanifest>true</wtpmanifest>

                              <downloadSources>true</downloadSources>

                              <downloadJavadocs>true</downloadJavadocs>

                          <manifest>${basedir}/src/main/resources/META-INF/MANIFEST.MF</manifest>

                        </configuration>

 

                  </plugin>

            </plugins>

      </build>

      <repositories>

            <repository>

                  <releases>

                        <enabled>false</enabled>

                  </releases>

                  <snapshots>

                        <enabled>true</enabled>

                  </snapshots>

                  <id>apache-maven-snapshots</id>

                  <url>http://people.apache.org/repo/m2-snapshot-repository</url>

            </repository>

            <repository>

                  <id>java.net</id>

                  <url>http://download.java.net/maven/1</url>

                  <layout>legacy</layout>

            </repository>

            <repository>

                  <id>java.net2</id>

                  <url>http://download.java.net/maven/2</url>

                  <layout>legacy</layout>

            </repository>

            <repository>

                  <id>repository.jboss.com</id>

                  <url>http://repository.jboss.com/maven2/</url>

                  <layout>default</layout>

            </repository>

            <repository>

                  <id>repo1</id>

                  <name>repo1</name>

                  <url>http://repo1.maven.org/maven2/</url>

                  <releases>

                        <updatePolicy>never</updatePolicy>

                  </releases>

            </repository>

      </repositories>

 

      <!-- Project dependencies -->

      <dependencies>

 

            <dependency>

                  <groupId>org.springframework</groupId>

                  <artifactId>spring-core</artifactId>

                  <version>2.5.6</version>

            </dependency>

            <dependency>

                  <groupId>org.springframework</groupId>

                  <artifactId>spring-beans</artifactId>

                  <version>2.5.6</version>

            </dependency>

            <dependency>

                  <groupId>org.springframework</groupId>

                  <artifactId>spring-context</artifactId>

                  <version>2.5.6</version>

            </dependency>

            <dependency>

                  <groupId>org.springframework</groupId>

                  <artifactId>spring-context-support</artifactId>

                  <version>2.5.6</version>

            </dependency>

            <dependency>

                  <groupId>org.springframework</groupId>

                  <artifactId>spring-orm</artifactId>

                  <version>2.5.6</version>

            </dependency>

            <dependency>

                  <groupId>org.springframework</groupId>

                  <artifactId>spring-aop</artifactId>

                  <version>2.5.6</version>

            </dependency>

            <dependency>

                  <groupId>org.springframework</groupId>

                  <artifactId>spring-jdbc</artifactId>

                  <version>2.5.6</version>

            </dependency>

            <dependency>

                  <groupId>org.springframework</groupId>

                  <artifactId>spring-web</artifactId>

                  <version>2.5.6</version>

            </dependency>

            <dependency>

                  <groupId>org.springframework</groupId>

                  <artifactId>spring-tx</artifactId>

                  <version>2.5.6</version>

            </dependency>

            <dependency>

                  <groupId>mysql</groupId>

                  <artifactId>mysql-connector-java</artifactId>

                  <version>5.0.4</version>

                  <scope>compile</scope>

            </dependency>

 

            <dependency>

                  <groupId>javax.el</groupId>

                  <artifactId>el-api</artifactId>

                  <version>1.0</version>

                  <scope>provided</scope>

            </dependency>

            <dependency>

                  <groupId>org.hibernate</groupId>

                  <artifactId>hibernate-entitymanager</artifactId>

                  <version>3.2.1.GA</version>

            </dependency>

            <dependency>

                  <groupId>org.apache.myfaces.core</groupId>

                  <artifactId>myfaces-api</artifactId>

                  <version>1.2.5</version>

                  <scope>compile</scope>

            </dependency>

            <dependency>

                  <groupId>org.apache.myfaces.core</groupId>

                  <artifactId>myfaces-impl</artifactId>

                  <version>1.2.5</version>

                  <scope>compile</scope>

            </dependency>

            <dependency>

                  <groupId>org.apache.myfaces.tomahawk</groupId>

                  <artifactId>tomahawk</artifactId>

                  <version>1.1.6</version>

                  <scope>runtime</scope>

                  <exclusions>

                        <exclusion>

                              <groupId>javax.servlet</groupId>

                              <artifactId>jstl</artifactId>

                        </exclusion>

                  </exclusions>

            </dependency>

            <dependency>

                  <groupId>jstl</groupId>

                  <artifactId>jstl</artifactId>

                  <version>1.2</version>

                  <scope>runtime</scope>

            </dependency>

 

            <dependency>

                  <groupId>com.sun.facelets</groupId>

                  <artifactId>jsf-facelets</artifactId>

                  <version>1.1.14</version>

            </dependency>

 

            <dependency>

                  <groupId>junit</groupId>

                  <artifactId>junit</artifactId>

                  <version>4.0</version>

                  <scope>test</scope>

            </dependency>

            <dependency>

                  <groupId>org.richfaces.framework</groupId>

                  <artifactId>richfaces-impl</artifactId>

                  <version>3.2.2.SR1</version>

                  <scope>compile</scope>

            </dependency>

            <dependency>

                  <groupId>org.richfaces.ui</groupId>

                  <artifactId>richfaces-ui</artifactId>

                  <version>3.2.2.SR1</version>

                  <scope>compile</scope>

            </dependency>

            <dependency>

                  <groupId>log4j</groupId>

                  <artifactId>log4j</artifactId>

                  <version>1.2.15</version>

                  <exclusions>

                        <exclusion>

                              <groupId>javax.mail</groupId>

                              <artifactId>mail</artifactId>

                        </exclusion>

                        <exclusion>

                              <groupId>com.sun.jdmk</groupId>

                              <artifactId>jmxtools</artifactId>

                        </exclusion>

                        <exclusion>

                              <groupId>com.sun.jmx</groupId>

                              <artifactId>jmxri</artifactId>

                        </exclusion>

                        <exclusion>

                              <groupId>javax.jms</groupId>

                              <artifactId>jms</artifactId>

                        </exclusion>

                  </exclusions>

            </dependency>

            <dependency>

                  <groupId>javax.servlet</groupId>

                  <artifactId>servlet-api</artifactId>

                  <version>2.5</version>

                  <scope>provided</scope>

            </dependency>

            <dependency>

                  <groupId>c3p0</groupId>

                  <artifactId>c3p0</artifactId>

                  <version>0.9.1.2</version>

            </dependency>

           

      </dependencies>

</project>

Most of you don't need explanation but for the rest I will explain the most strange sections. Starting from last one c3p0 – I use it because sometimes mysql closes my idle connection which are in the connection pool. The c3p0 is used to execute test query every X minutes like SELECT 1. The dependancy javax.servlet you dont need it because you deploy on web container but I’ve added it because sometimes I need to cast somethink to HttpServletRequest or HttpSession and I want to have it in my eclipse classpath. Log4j is a must for every project that’s why it is included here. The other dependancies are richfaces, jsf, facelets, hibernate and spring I don't see something strange there so if you don't understand something post a comment.

Next we will use Spring right ? so lets paste the applicationContext.xml ( note that it is not big because we will use @Autowired and @Component to autowire and to register our spring beans ).

<?xml version="1.0" encoding="UTF-8"?>

<beans

      xmlns="http://www.springframework.org/schema/beans"

      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

      xmlns:context="http://www.springframework.org/schema/context"

    xmlns:tx="http://www.springframework.org/schema/tx"

      xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd

      http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd

      http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd

    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"

     default-autowire="byName">

      

      <context:annotation-config/>

      <tx:annotation-driven proxy-target-class="true" />

     

      <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">

      </bean>

     

      <context:component-scan base-package="org.joke.myproject">

      </context:component-scan>

     

       <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">

          <property name="jdbcUrl"><value>jdbc:mysql://localhost:3306/asomtsp?autoReconnect=true&amp;characterEncoding=utf8</value></property>

          <property name="driverClass"><value>com.mysql.jdbc.Driver</value></property>

          <property name="user"><value>root</value></property>

          <property name="password"><value>12345678</value></property>

          <property name="maxStatements"><value>0</value></property>

          <property name="maxIdleTime"><value>1800</value></property>

          <property name="minPoolSize"><value>5</value></property>

          <property name="maxPoolSize"><value>150</value></property>

          <property name="initialPoolSize"><value>20</value></property>

          <property name="acquireIncrement"><value>5</value></property>

          <property name="numHelperThreads"><value>10</value></property> 

          <property name="idleConnectionTestPeriod"><value>3600</value></property>

            <property name="preferredTestQuery"><value>select 1;</value></property>

      </bean>

     

      <bean id="sessionFactory"

 class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">

            <property name="configLocation" value="classpath:hibernate.cfg.xml">

            </property>

            <property name="dataSource" ref="dataSource"></property>

      </bean>

</beans>

The default-autowire="byName" attribute is used because I don't want to tell ref bean ref bean for each bean :).

The tag 'context:annotation-config' tells spring to go the annotation way.

The tag 'context:component-scan' tells spring to look for annotated classes in the specified package. Once you put this tag you do not need the 'context:annotation-config' tag.

Sometimes when we auto wire by type there may be multiple beans of the same type (or inherited type). One case is if you define multiple datsasources. How do you tell your bean in that case which one to pick. In this case use @Qualifier("beanid") to select the specific one.

I don't think I have to explain something about transactionManager and dataSource. If you have questions feel free to post a comment.

Next the hibernate.cfg.xml. Since all my database related configurations are in the applicationContext.xml the hibernate.cfg.xml contains only all my mapped classes needed for sessionFactory.

<?xml version='1.0' encoding='utf-8'?>

<!DOCTYPE hibernate-configuration PUBLIC

        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"

        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>

      <session-factory>

            <!-- SQL dialect -->

            <property name="dialect">org.hibernate.dialect.MySQLDialect</property>

            <!-- Enable formatted SQL in the logs -->

            <property name="format_sql">true</property>

            <!-- Hibernate mappings references -->

            <mapping class="org.joke.myproject.entity.Message" />

      </session-factory>

</hibernate-configuration>

I have only one entity called Messages and I’ve used annotations for mappings not another xml file. You can use whatever you want annotations or mapping.xml file. If you are using xml file for mappings you will have <mapping resource="Messages.hbm.xml"/> instead of mapping class.

Almost finished. Lets integrate now Spring with JSF. We will want to use spring container for creating a JSF managed beans. So open faces-config.xml and add the fallowing lines  in the application tag. Full example looks like :

<?xml version="1.0" encoding="UTF-8"?>

<faces-config xmlns="http://java.sun.com/xml/ns/javaee"

      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd"

      version="1.2">

      <!—navigation rules goes here -->

      <application>

         <el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>

      </application>

</faces-config>

After adding the SpringBeanFacesELResolver lets do the final step : web.xml

<?xml version="1.0"?>

 

      <!--

            * Licensed to the Apache Software Foundation (ASF) under one * or more

            contributor license agreements. See the NOTICE file * distributed with

            this work for additional information * regarding copyright ownership.

            The ASF licenses this file * to you under the Apache License, Version

            2.0 (the * "License"); you may not use this file except in compliance

            * with the License. You may obtain a copy of the License at * *

            http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by

            applicable law or agreed to in writing, * software distributed under

            the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES

            OR CONDITIONS OF ANY * KIND, either express or implied. See the

            License for the * specific language governing permissions and

            limitations * under the License.

      -->

<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

      xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"

      version="2.4">

 

      <description>myproject web.xml</description>

      <session-config>

       <session-timeout>30</session-timeout>

    </session-config>

      <context-param>

            <param-name>org.jboss.jbossfaces.WAR_BUNDLES_JSF_IMPL</param-name>

            <param-value>true</param-value>

      </context-param>

 

      <!--

            Configure tomahawk taglib <context-param>

            <param-name>facelets.LIBRARIES</param-name>

            <param-value>/WEB-INF/tomahawk.taglib.xml</param-value>

            </context-param>

      -->

      <!-- Use Documents Saved as *.xhtml -->

      <context-param>

            <param-name>javax.faces.DEFAULT_SUFFIX</param-name>

            <param-value>.xhtml</param-value>

      </context-param>

 

      <!-- Special Debug Output for Development -->

      <context-param>

            <param-name>facelets.DEVELOPMENT</param-name>

            <param-value>true</param-value>

      </context-param>

 

      <context-param>

            <param-name>javax.faces.STATE_SAVING_METHOD</param-name>

            <param-value>client</param-value>

      </context-param>

      <context-param>  

            <param-name>org.apache.myfaces.NUMBER_OF_VIEWS_IN_SESSION</param-name>

            <param-value>20</param-value>

      </context-param>

      <context-param>

            <param-name>org.apache.myfaces.SERIALIZE_STATE_IN_SESSION</param-name>

            <param-value>true</param-value>

      </context-param>

      <context-param>

            <param-name>org.apache.myfaces.COMPRESS_STATE_IN_SESSION</param-name>

            <param-value>true</param-value>

      </context-param>

      <context-param>

            <param-name>org.apache.myfaces.ALLOW_JAVASCRIPT</param-name>

            <param-value>true</param-value>

      </context-param>

      <context-param>

            <param-name>org.apache.myfaces.DETECT_JAVASCRIPT</param-name>

            <param-value>false</param-value>

      </context-param>

      <context-param>

            <param-name>org.apache.myfaces.PRETTY_HTML</param-name>

            <param-value>true</param-value>

      </context-param>

      <context-param>

            <param-name>org.apache.myfaces.AUTO_SCROLL</param-name>

            <param-value>true</param-value>

      </context-param>

 

      <context-param>

            <param-name>org.apache.myfaces.SECRET</param-name>

            <param-value>NzY1NDMyMTA=</param-value>

      </context-param>

 

      <context-param>

            <param-name>org.apache.myfaces.VALIDATE</param-name>

            <param-value>true</param-value>

      </context-param>

 

      <context-param>

            <param-name>org.apache.myfaces.READONLY_AS_DISABLED_FOR_SELECTS</param-name>

            <param-value>true</param-value>

      </context-param>

 

      <context-param>

            <param-name>org.apache.myfaces.ADD_RESOURCE_CLASS</param-name>

            <param-value>

                  org.apache.myfaces.renderkit.html.util.DefaultAddResource

            </param-value>

      </context-param>

 

      <context-param>

            <param-name>org.apache.myfaces.RESOURCE_VIRTUAL_PATH</param-name>

            <param-value>/faces/myFacesExtensionResource</param-value>

      </context-param>

 

      <context-param>

            <param-name>org.apache.myfaces.CHECK_EXTENSIONS_FILTER</param-name>

            <param-value>true</param-value>

      </context-param>

 

      <context-param>

            <param-name>javax.faces.PARTIAL_STATE_SAVING_METHOD</param-name>

            <param-value>false</param-value>

      </context-param>

      <context-param>

            <param-name>org.richfaces.SKIN</param-name>

            <param-value>blueSky</param-value>

      </context-param>

      <context-param>

            <param-name>org.ajax4jsf.VIEW_HANDLERS</param-name>

            <param-value>com.sun.facelets.FaceletViewHandler</param-value>

      </context-param>

      <filter>

            <display-name>RichFaces Filter</display-name>

            <filter-name>richfaces</filter-name>

            <filter-class>org.ajax4jsf.Filter</filter-class>

      </filter>

      <!-- Extensions Filter -->

      <filter>

            <filter-name>extensionsFilter</filter-name>

            <filter-class>org.apache.myfaces.webapp.filter.ExtensionsFilter</filter-class>

            <init-param>

                  <param-name>uploadMaxFileSize</param-name>

                  <param-value>100m</param-value>

            </init-param>

            <init-param>

                  <param-name>uploadThresholdSize</param-name>

                  <param-value>100k</param-value>

            </init-param>

      </filter>

      <filter>

            <filter-name>sessionFilter</filter-name>

            <filter-class>

                  org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>

      </filter>

      <filter-mapping>

            <filter-name>sessionFilter</filter-name>

            <url-pattern>*.jsf</url-pattern>

      </filter-mapping>

 

      <filter-mapping>

            <filter-name>richfaces</filter-name>

            <servlet-name>Faces Servlet</servlet-name>

            <dispatcher>REQUEST</dispatcher>

            <dispatcher>FORWARD</dispatcher>

            <dispatcher>INCLUDE</dispatcher>

      </filter-mapping>

      <filter-mapping>

            <filter-name>extensionsFilter</filter-name>

            <url-pattern>*.jsf</url-pattern>

      </filter-mapping>

      <filter-mapping>

            <filter-name>extensionsFilter</filter-name>

            <url-pattern>/faces/*</url-pattern>

      </filter-mapping>

 

      <!-- Listener, to allow Jetty serving MyFaces apps -->

      <listener>

            <listener-class>

                  org.apache.myfaces.webapp.StartupServletContextListener</listener-class>

      </listener>

      <!--  spring integration  -->

      <listener>

            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

      </listener>

      <listener>

            <listener-class>

                  org.springframework.web.context.request.RequestContextListener</listener-class>

      </listener>

 

      <!-- Faces Servlet -->

      <servlet>

            <servlet-name>Faces Servlet</servlet-name>

            <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>

            <load-on-startup>1</load-on-startup>

      </servlet>

 

      <!-- Faces Servlet Mapping -->

      <servlet-mapping>

            <servlet-name>Faces Servlet</servlet-name>

            <url-pattern>*.jsf</url-pattern>

      </servlet-mapping>

 

      <!-- Welcome files -->

      <welcome-file-list>

            <welcome-file>index.jsp</welcome-file>

            <welcome-file>index.html</welcome-file>

      </welcome-file-list>

 

</web-app>

Most of the parts are from the myfaces implementation. The important aspects are :

RichFaces integration using

org.richfaces.SKIN param and richfaces filter (org.ajax4jsf.Filter). 


You can read about richfaces integration here:http://docs.jboss.org/richfaces/3.3.1.GA/en/devguide/html_single/


For jetty+myfaces we need to use this listener : org.apache.myfaces.webapp.StartupServletContextListener



And for Spring integration we need this two listeners : org.springframework.web.context.ContextLoaderListener and org.springframework.web.context.request.RequestContextListener



Thats ALL!


Now Lets start coding :)


Our Managed Beans will dont need any XML configuration they will look like this :



@Component


@Scope("request")


public class MessagesBean {



      @Autowired


      private MessagesService messagesService;


//use messagesService for what you want



}


 


The services are spring beans ( have @Component annotation) and are autowired in JSF Managed Beans/ Backing Beans. Our services looks like this the @Transaction annotation is used for creating transaction. You can read about it at  http://static.springsource.org/spring/docs/2.0.x/reference/transaction.html  part : 9.5.6. Using @Transactional.



@Component


public class MessagesService {



      @Autowired


      private MessagesDAO messagesDAO;


@Transactional


      public List<Message> listMessages() {


            List<Message> messages = messagesDAO.findAll();


            return messages;


      }


//use messagesDao for what you want



}


Our DAOs look like this (they are spring beans again and are autowired in service layer).


@Component


public class MessagesDAO extends GenericDaoImpl<Message, Integer> {


 


      @Override


      protected Class<Message> getEntityClass() {


            return Message.class;


      }


//add additional dao methods if you want



}


Finally ! Thats all. After playing a while with project like this you will notice how fast is to create new service, dao, backing bean/managed bean because you don't need to type any XML.




Feel free to post comments and questions.













Comments

Yasen Simeonov said…
Congrats dude,

in general i hate blogs,
but yours is the second which i put in favorites.
I find it very useful, keep going the same way.

Best .. Yasen
Coalas said…
Hi

could you link to this article an archive with maven project ready to import in eclipse?
It would be very helpful, for someone like me ,who is very new to spring and all Java technologies :)

thank you
Chris
imrabti said…
Thank you.

Looks very well organized I really heat the old approach using the faces-context to register the managed beans.

Popular posts from this blog

Hibernate Generic DAO.

When you use Hibernate and DAO pattern it is a good idea to use a Generic Base Dao. The fallowing code snippet contains GenericDAO that is a base class for all my DAO classes. This GenericDAO uses HibernateDaoSupport from Spring for its implementation if you want you can use JpaDaoSupport or JdbcDaoSupport in your projects. My Generic DAO interface looks like this : package org.joke.myproject.dao.base; import java.io.Serializable; import java.util.List; /** * @author Naiden Gochev * @param <E> * @param <PK> */ public interface GenericDao<E,PK  extends Serializable> {     PK save(E newInstance);     void update(E transientObject);     void saveOrUpdate(E transientObject);     void delete(E persistentObject);     E findById(PK id);     List<E> findAll();     List<E> findAllByProperty(String propertyName,Object value); } All method names are very common so I don't

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 j

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