Duplicate class/entity mapping

Hi all, i have a legacy application which uses hibernate to connect to oracle database. When we test this application with oracle 12c, there were no issues. However, when we test the application with the same database on oracle 19c, we encountered org.hibernate.InvalidMappingException: Could not parse mapping document from resource hibernate.hbm.xml

Is someone able to advise/guide me on how i can troubleshoot/resolve this issue?

Code to call hibernate

public void requestBegin(SCESession mySession) {
		// TODO Auto-generated method stub

Logger logger = null;
DBInfo dBInfo = null;
String sessionId = CDG_JMS_Constants.EMPTY;
String dbConfigPath = CDG_JMS_Constants.EMPTY;

logger = Logger.getLogger(mySession.getServlet().getServletContext().getInitParameter(CDG_JMS_Constants.LOGGERPATH));
sessionId = mySession.getSessionId();
dbConfigPath = mySession.getVariableField(IProjectVariables.DB__CONFIG__PATH).getStringValue();

//Setting The DB Info To The DB Info Object
dBInfo = new DBInfo();
dBInfo.setLogger(logger);
dBInfo.setSessionID(sessionId);
dBInfo.setConfigPath(dbConfigPath);

//Calling To The DNIS Mapping Table for The DB To Get The HotLine Number
String dnis = mySession.getVariableField(IProjectVariables.SESSION,IProjectVariables.SESSION_FIELD_DNIS).getStringValue();
	if(null != dnis && !CDG_JMS_Constants.EMPTY.equalsIgnoreCase(dnis.trim())){
		try{
			DBServiceImpl dbServiceImpl = new DBServiceImpl(dBInfo);
			IvrDnisMapping ivrDnisMapping =  dbServiceImpl.findIvrDnisMappingForVdn(dnis);
			if(null != ivrDnisMapping.getHotlineNumber())
            {
				dnis = ivrDnisMapping.getHotlineNumber();
			}
				trace.writeln(ITraceInfo.TRACE_LEVEL_DEBUG, "HotLine Number Recieved From The DB Look Up : "+dnis);
					
			}catch (Exception e) {
					if(mySession.isDDTraceEnabled()){
						trace.writeln(ITraceInfo.TRACE_LEVEL_DEBUG, "Exception Occured while Performing DB LookUp For HotLine Number :" + e.getMessage());
						Util.doAlarmEvent(mySession, "WARNING", "Exception Occured while Performing DB LookUp For HotLine Number :" + e.getMessage());
					}
				}				
			}
}
HibernateSessionFactory.class

public class HibernateSessionFactory {
	
	private static Configuration configuration = new Configuration();
	private static org.hibernate.SessionFactory sessionFactory;

	private HibernateSessionFactory() {
	}

	/**
	 * @param dbInfo
	 * @return
	 * @throws HibernateException
	 */
	public static Session getSession(DBInfo dbInfo) throws HibernateException {
			if (sessionFactory == null) {
				dbInfo.getLogger().info("Session Info is Null. Creating... ");
				buildSessionFactory(dbInfo);
			}
			dbInfo.getLogger().info("Session Info Created. ");
			return sessionFactory.openSession();
	}

	/**
	 * Build hibernate session factory
	 * 
	 */
	private static void buildSessionFactory(DBInfo dbInfo) {
		try {
			dbInfo.getLogger().info("Config Path: "+dbInfo.getConfigPath());
			configuration.configure(new File(dbInfo.getConfigPath()));
			dbInfo.getLogger().info("Hibernate Configuration configured.");
			sessionFactory = configuration.buildSessionFactory();
			dbInfo.getLogger().info("Session Built.");
		} catch (Exception e) {
			dbInfo.getLogger().error("Error creating Session Factory "+ e);
			
			String stackTrace = "";
			
			for (StackTraceElement element : e.getStackTrace())
				stackTrace += element.toString() + "\n";
			
			dbInfo.getLogger().error(" : Stack Trace: "+ stackTrace);
			dbInfo.getLogger().error(" : Cause: "+ e.getCause());
		}
	}

}
DBServiceImpl.class

public class DBServiceImpl implements DBService {

	Logger logger = null;
	String sessionId = CDG_DB_Constants.EMPTY;
	String configPath = CDG_DB_Constants.EMPTY;
	File cfgfile = null;
	DBInfo dbInfo;
	public DBServiceImpl(DBInfo dbInfo) {
		logger = dbInfo.getLogger();
		sessionId = dbInfo.getSessionID();
		configPath = dbInfo.getConfigPath();
		this.dbInfo = dbInfo;
		cfgfile = new File(configPath);
	}
@Override
	public IvrDnisMapping findIvrDnisMappingForVdn(String vdn) {
		logger.debug(sessionId + " : *****Loading IvrDnisMapping for VDN: "+vdn+" *****");
		Session session = null;
		try {
			session = HibernateSessionFactory.getSession(dbInfo); 
			return (IvrDnisMapping) session.load(IvrDnisMapping.class, vdn);
		} catch (HibernateException e) {
			logger.error(sessionId + " : Exception occured while Loading IvrDnisMapping for VDN: "+vdn+". "+ e.getMessage());
			logger.error(sessionId + " : Stack Trace: "+ e.getStackTrace());
			logger.error(sessionId + " : Cause: "+ e.getCause());
			return null;
		}finally{
			if (session != null) {
				session.close();
			}
			logger.debug(sessionId + " : *****Loading IvrDnisMapping for VDN: "+vdn+" *****");
		}
	}
}

Please post the full stack trace of the exception.

Hi Beikov,

Stack trace as below/

08/06/2023 14:56:17:511  INFO - Config Path: D:\Program Files\Apache Software Foundation\Tomcat 6.0\lib\hibernate.cfg.xml
08/06/2023 14:56:17:552 ERROR - Error creating Session Factory org.hibernate.InvalidMappingException: Could not parse mapping document from resource hibernate.hbm.xml
08/06/2023 14:56:17:552 ERROR -  : Stack Trace: org.hibernate.cfg.Configuration.addResource(Configuration.java:671)
org.hibernate.cfg.Configuration.parseMappingElement(Configuration.java:1679)
org.hibernate.cfg.Configuration.parseSessionFactory(Configuration.java:1647)
org.hibernate.cfg.Configuration.doConfigure(Configuration.java:1626)
org.hibernate.cfg.Configuration.doConfigure(Configuration.java:1600)
org.hibernate.cfg.Configuration.configure(Configuration.java:1554)
com.avaya.ept.cdg.service.config.HibernateSessionFactory.buildSessionFactory(HibernateSessionFactory.java:48)
com.avaya.ept.cdg.service.config.HibernateSessionFactory.getSession(HibernateSessionFactory.java:35)
com.avaya.ept.cdg.service.impl.DBServiceImpl.findIvrDnisMappingForVdn(DBServiceImpl.java:425)
flow.Set_JMSInfo.requestBegin(Set_JMSInfo.java:182)
com.avaya.sce.runtime.AppServlet.processRequest(AppServlet.java:81)
com.avaya.sce.runtime.SCEServlet.requestHandler(SCEServlet.java:282)
com.avaya.sce.runtime.SCEServlet.doPost(SCEServlet.java:189)
javax.servlet.http.HttpServlet.service(HttpServlet.java:643)
javax.servlet.http.HttpServlet.service(HttpServlet.java:723)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:615)
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:861)
org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:606)
org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
java.lang.Thread.run(Thread.java:750)

08/06/2023 14:56:17:552 ERROR -  : Cause: org.hibernate.DuplicateMappingException: Duplicate class/entity mapping com.avaya.ept.cdg.beans.AdhocMessage

Is it possible that you run Configuration.configure() multiple times on the same object? You can debug into InFlightMetadataCollectorImpl.addEntityBinding() to see how this happens.

hi beikov, if i understand the source code correctly, the code mentioned above should be the first instance .configure() is called. the same source code is able to connect to 19c via proxy through 12c database…

I don’t know how the code in com.avaya.ept.cdg.service.config.HibernateSessionFactory looks like, so I can’t help you with that. You can debug to the addEntityBinding method I referred to before and figure out what is happening for sure :slight_smile:

Hi Beikov, attached the snippet for com.avaya.ept.cdg.service.config.HibernateSessionFactory
Base on the error message, it is pointing to the very first class in hibernate.hbm.xml. Could there be a mismatch or something with oracle 19c?

package com.avaya.ept.cdg.service.config;

import java.io.File;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.cfg.Configuration;

import com.avaya.ept.cdg.beans.DBInfo;

/**
 * Author:jerald.a
 *
 */

/**
 * Configures and provides access to Hibernate sessions
 */
public class HibernateSessionFactory {
	
	private static Configuration configuration = new Configuration();
	private static org.hibernate.SessionFactory sessionFactory;

	private HibernateSessionFactory() {
	}

	/**
	 * @param dbInfo
	 * @return
	 * @throws HibernateException
	 */
	public static Session getSession(DBInfo dbInfo) throws HibernateException {
			if (sessionFactory == null) {
				dbInfo.getLogger().info("Session Info is Null. Creating... ");
				buildSessionFactory(dbInfo);
			}
			dbInfo.getLogger().info("Session Info Created. ");
			return sessionFactory.openSession();
	}

	/**
	 * Build hibernate session factory
	 * 
	 */
	private static void buildSessionFactory(DBInfo dbInfo) {
		try {
			dbInfo.getLogger().info("Config Path: "+dbInfo.getConfigPath());
			configuration.configure(new File(dbInfo.getConfigPath()));
			dbInfo.getLogger().info("Hibernate Configuration configured.");
			sessionFactory = configuration.buildSessionFactory();
			dbInfo.getLogger().info("Session Built.");
		} catch (Exception e) {
			dbInfo.getLogger().error("Error creating Session Factory "+ e);
			
			String stackTrace = "";
			
			for (StackTraceElement element : e.getStackTrace())
				stackTrace += element.toString() + "\n";
			
			dbInfo.getLogger().error(" : Stack Trace: "+ stackTrace);
			dbInfo.getLogger().error(" : Cause: "+ e.getCause());
		}
	}

}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
 "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
	<class name="com.avaya.ept.cdg.beans.AdhocMessage" table="IVR_ADHOC_MESSAGE">
		<composite-id>
			<key-property name="functionality" type="string" length="100" />
			<key-property name="msgLanguage" column="MSG_Language" type="string" length="10" />
		</composite-id>

		<property name="status"  not-null="true" type="string" length="10" />
		<property name="wavFile" column="WAVEFILE" not-null="false" type="string" length="100" />
		<property name="interrupt" type="string" not-null="false" length="10" />
		<property name="startDateTime" column="Start_Date_Time" not-null="false"  type="timestamp" />
		<property name="endDateTime" column="End_Date_Time" not-null="false"  type="timestamp"/>		
		<property name="lastChangedBy" type="string" column="Last_Changed_By" not-null="false"  length="100" />
		<property name="lastChangedOn" type="timestamp" column="Last_Changed_On" not-null="false" />
		<property name="modifyReason" column="modify_Reason" type="string" not-null="false"  length="100" />
		<property name="ivrLanguage" column="IVR_LANGUAGE" type="string" not-null="false"  length="10" />
		<property name="waveFileList" column="WAVEFILELIST" type="string" not-null="false"  length="105" />
	</class>

	<class name="com.avaya.ept.cdg.beans.CallHistory" table="IVR_CALL_HISTORY">

		<id name="ucid" type="string" length="50"/>
		
		<property name="startDateTime" column="Start_Date_Time" not-null="true" type="timestamp" />
		<property name="endDateTime" column="End_Date_Time" not-null="true" type="timestamp" />
		<property name="callDuration" column="CALL_DUR" not-null="true" type="integer"/>
		<property name="cliEntered" type="string" length="3" not-null="true" column="CLI_ENTERED"/>
		<property name="clid" type="string" not-null="false" length="30" />
		<property name="dnis" type="string" not-null="false" length="30" />
		<property name="lastMenuID" column="LAST_MENU_ID" type="string" not-null="false" length="10" />
		<property name="custLanguage" column="CUST_LANGUAGE" type="string" not-null="false"  length="10" />
		<property name="customerName" column="CUSTOMER_NAME" type="string" not-null="false"  length="50" />
		<property name="priority" type="string" not-null="false"  length="10" />
		<property name="duplicateCallFlag" column="DUPLICATE_CALL_FLAG" type="string" not-null="false" 	length="10" />
		<property name="bookingStatus" column="BOOKING_STATUS" type="string" not-null="false" length="10" />
		<property name="bookingId" column="BOOKING_ID" type="string" not-null="false"  length="20" />
		<property name="jobId" column="JOB_ID" type="string" not-null="false" length="20" />
		<property name="taxiNumber" column="taxi_Number" type="string" not-null="false"  length="20" />
		<property name="transferedCallFlag" column="TRANSFERRED_CALL_FLAG" type="string" not-null="false" length="2" />
		<property name="transferCount" column="TRANSFER_COUNT" type="string" not-null="false" length="2" />
		<property name="transferReason" column="TRANSFER_REASON" type="string" not-null="false" length="10" />
		<property name="answeringAgentId" column="ANSWERING_AGENT_ID" type="string" not-null="false" length="10" />
		<property name="answeringAgentSkill" column="ANSWERING_AGENT_SKILL" type="string" not-null="false" length="20" />
		<property name="queueTime" column="QUEUETIME" type="string" not-null="false"  length="10" />
		<property name="lastMenu1" column="LASTMENU_1" type="string" not-null="false" length="50" />
		<property name="lastMenu2" column="LASTMENU_2" type="string" not-null="false" length="50" />
		<property name="lastMenu3" column="LASTMENU_3" type="string" not-null="false" length="50" />
		<property name="lastMenu4" column="LASTMENU_4" type="string" not-null="false" length="50" />
		
		<bag name="hostTransaction" cascade="all" inverse="true" table="IVR_HOST_TRANSACTIONS" lazy="true">
			<key column="ucid"  not-null="true" />
			<one-to-many class="com.avaya.ept.cdg.beans.HostTransactions" />
		</bag>
	</class>

	<class name="com.avaya.ept.cdg.beans.HostTransactions" table="IVR_HOST_TRANSACTIONS" >
		<composite-id>
			<key-property name="ucid" type="string"  length="50"/>
			<key-property name="requestDateTime" column="Request_Date_Time" type="timestamp" />
		</composite-id>
			
		<property name="icdMessageId" column="ICD_MSG_ID" type="string" not-null="true" length="20" />
		<property name="transactionName" column="transaction_Name" type="string" not-null="true" length="50" />
		<property name="responseDateTime" column="Response_Date_Time" type="timestamp" not-null="true"/>
		<property name="requestMessage" column="req_message" type="string" not-null="false" length="2500" />
		<property name="responseMessage" column="res_Message" type="string" not-null="false" length="3500" />
	</class>

	<class name="com.avaya.ept.cdg.beans.MenuDescription" table="IVR_MENU_DESC">	
		<id name="imdMenuId" column="IMD_MENU_ID" type="string" length="10"/>
		
		<property name="vdn" not-null="true" type="string" length="10" />
		<property name="imdMenuName" column="imd_Menu_Name" not-null="true" type="string" length="100" />
		<property name="lastChangedON" column="last_Changed_ON" type="timestamp" not-null="false"/>
		<property name="lastChangedBY" column="last_Changed_BY" type="string" length="100" />
	</class>
	
	<class name="com.avaya.ept.cdg.beans.Usage" table="IVR_USAGE">
		<composite-id>
			<key-property name="ucid" type="string" length="50"/>
			<key-property name="iuOrder" type="java.lang.Integer" column="IU_ORDER"/>
		</composite-id>
		<property name="menuId" column="MENU_ID" not-null="false" type="string" length="10" />
		<property name="iuDateTime" column="Iu_Date_Time" not-null="true" type="timestamp"/>
		<property name="iuRemarks" column="Iu_Remarks" not-null="true" type="string" length="50" />
	</class>

	<class name="com.avaya.ept.cdg.beans.TTSSMS" table="IVR_TTS_SMS">
		<id name="flag"  column="Flag" type="string" length="10"/>
	</class>
	
	<class name="com.avaya.ept.cdg.beans.HostMapping" table="IVR_HOST_MAPPING">
		<composite-id>
			<key-property name="functionality" column="FUNCTIONALITY" type="string" length="50"/>
			<key-property name="hostValue" column="HOST_VALUE" type="string" length="10"/>
		</composite-id>
		
		<property name="msgLanguage" column="MSG_Language" type="string" length="10" not-null="true"/>
		<property name="wavfile" type="string" length="100" not-null="false"/>
		<property name="status" type="string" length="10" not-null="true"/>
		<property name="msgDescription" column="MSG_Description" type="string" length="100" not-null="false"/>
		<property name="lastChangedBy" column="Last_Changed_By" type="string" length="100" not-null="false"/>
		<property name="lastChangedOn" column="Last_Changed_On" type="string" not-null="false"/>		
	</class>
	
	<class name="com.avaya.ept.cdg.beans.CallOutRequest" table="IVR_CALLOUT_REQUEST">
		<id name="requestId" column="REQ_ID" type="int">
			<generator class="sequence">
			<param name="sequence">IVR_CALLOUT_REQ_ID_SEQ</param>
			</generator>
		</id>
		<property name="jobId" column="JOB_ID" type="string" length="20" not-null="true"/>
		<property name="taxiId" column="TAXI_ID" type="string" length="20" not-null="true"/>
		<property name="addressId" column="ADDRESS_ID" type="string" length="20" not-null="false"/>
		<property name="requestDateTime" column="REQUEST_DATE_TIME" type="timestamp"  not-null="true"/>
		<property name="callBackNumber" column="CALLBACK_NUMBER" type="string" length="30" not-null="true"/>
		<property name="callOutResult" column="CALLOUT_RESULT" type="string" not-null="true"/>
		<property name="ucid"  type="string" not-null="false"/>	
		<property name="initiatorId" column="INITIATOR_ID" type="string" length="10" not-null="false"/>
	</class>
	
	<class name="com.avaya.ept.cdg.beans.IvrDnisMapping" table="IVR_DNIS_MAPPING" lazy="false">	
		<id name="vdn" column="VDN" type="string" length="10"/>		
		<property name="hotlineNumber" column="HOTLINE_NUMBER" not-null="true" type="string" length="20" />
		<property name="hotlineDescription" column="HOTLINE_DESCRIPTION" not-null="true" type="string" length="30" />
	</class>
	
	<class name="com.avaya.ept.cdg.beans.AutoparkFailover" table="AUTOPARKFAILOVER" lazy="false">	
		<id name="ucid2" column="UCID2" type="string" length="50"/>
		<property name="apDateTime" column="AP_DATE_TIME" not-null="false"  type="timestamp" />		
		<property name="ucid1" column="UCID1" not-null="true" type="string" length="50" />
		<property name="clid" column="CLID" not-null="true" type="string" length="20" />
		<property name="bookingId" column="BOOKING_ID" not-null="true" type="string" length="20" />
		<property name="jobId" column="JOB_ID" not-null="true" type="string" length="20" />
		<property name="numOfTaxis" column="NUM_OF_TAXIS" not-null="false" type="string" length="20" />
		<property name="langPref" column="LANG_PREF" not-null="false" type="string" length="20" />
		<property name="parkType" column="PARKTYPE" not-null="false" type="string" length="50" />
		<property name="notifyBySms" column="NOTIFY_BY_SMS" not-null="false" type="string" length="20" />
		<property name="queuePriority" column="QUEUE_PRIORITY" not-null="false" type="string" length="10" />
		<property name="transferReason" column="TRANSFER_REASON" not-null="false" type="string" length="10" />
		<property name="blacklisted" column="BLACKLISTED" not-null="false" type="string" length="10" />
		<property name="hotLineNumber" column="HOTLINE_NUMBER" not-null="false" type="string" length="10" />
	</class>
</hibernate-mapping>

Your code is not thread safe, so depending on the environment you are running in, this code potentially configures the same hbm.xml mapping multiple times. Use the following instead, or even better, start using some proper runtime like a Jakarta EE Server or Quarkus:

public class HibernateSessionFactory {
	
	private static volatile org.hibernate.SessionFactory sessionFactory;

	private HibernateSessionFactory() {
	}

	public static Session getSession(DBInfo dbInfo) throws HibernateException {
		return getSessionFactory(dbInfo).openSession();
	}

	private static org.hibernate.SessionFactory getSessionFactory(DBInfo dbInfo) {
org.hibernate.SessionFactory factory = sessionFactory;
		if (factory == null) {
			synchronized (HibernateSessionFactory.class) {
				factory = sessionFactory;
				if (factory == null) {
					dbInfo.getLogger().info("Config Path: "+dbInfo.getConfigPath());
					Configuration configuration = new Configuration();
					configuration.configure(new File(dbInfo.getConfigPath()));
					sessionFactory = factory = configuration.buildSessionFactory();
				}
			}
		}
		return factory;
	}

}

hi beikov, i have tried your code but this time, the code got stuck in this section. There are no error or error stack trace.

Configuration configuration = new Configuration();
configuration.configure(new File(dbInfo.getConfigPath()));
sessionFactory = factory = configuration.buildSessionFactory();

Then you have to debug your application to see what is going on or even better, like I suggested previously, use a proper runtime that does this heavy lifting for you.