TopLink - Common Errors - ClassCastException

Are you facing a class cast exception while using Oracle TopLink?
For example - com.entity.Organization cannot be cast to com.entity.Organization

In my experience, this issue occurred sporadically and was not consistent. The reason this occurs is because multiple instances of Entity Manager have been created in your application session. The class loader is hence unable to determine the instance of the class that is to be loaded

Here is how I was able to workaround the issue:

  • Create a listener class (myListner) as shown below
    • Override the contextInitialized method to create an entity manager as soon as the application session is initiated
    • Override the contextDestroyed method to release the entity manager as soon as the application session ends
  • This will ensure only a single instance of entity manager exists at any point in time. Thus, eliminating the root cause.


package com.db.dao;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

public class myListener implements ServletContextListener {
    private static String persistenceUnitName = "Persistent_Unit_Name";
    private static EntityManagerFactory emf = Persistence.createEntityManagerFactory(persistenceUnitName);

    public myListener() {
    }

    @Override
    public void contextInitialized(ServletContextEvent event) {
        if (!emf.isOpen()) {
            emf = Persistence.createEntityManagerFactory(persistenceUnitName);
        }
    }

    @Override
    public void contextDestroyed(ServletContextEvent event) {
        if (emf != null) {
            emf.close();
        }
    }

}

  • Register the listener class in your web.xml
<web-app version="2.5" 
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
   xmlns="http://java.sun.com/xml/ns/javaee" 
   xsi:schemalocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
   version="2.5" xmlns="http://java.sun.com/xml/ns/javaee">
  <display-name>myTopLinkProject</display-name>
  <description>Sample TopLink Application</description>
  <filter>
    <filter-name>JpsFilter</filter-name>
    <filter-class>oracle.security.jps.ee.http.JpsFilter</filter-class>
    <init-param>
      <param-name>enable.anonymous</param-name>
      <param-value>true</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>JpsFilter</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>INCLUDE</dispatcher>
  </filter-mapping>
  <listener>
    <description>Web Application Listener</description>
    <display-name>myListener</display-name>
    <listener-class>ul.iam.db.dao.myListener</listener-class>
  </listener>
</web-app>





Please share your feedback below. Hope you find this helpful!

CaptiveCode


How To: Configure JTA Data Source in TopLink persistence.xml

Here is an example of a persistence.xml when using a data source:

<persistence version="2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
   xmlns="http://java.sun.com/xml/ns/persistence" 
   xsi:schemalocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
  <persistence-unit name="Sample" transaction-type="JTA">
    <description>Attribute Data Store</description>
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <jta-data-source>jdbc/SampleDataSource</jta-data-source>
    <properties>
      <property name="toplink.logging.level" value="INFO">
    </property></properties>
  </persistence-unit>
</persistence>





Please share your feedback below. Hope you find this helpful!

CaptiveCode


Did you know? Oracle Mobile: JSONBeanSerializationHelper Does Not Respect Case!

Oracle Mobile is a framework provided by Oracle that enables developers to build cross-platform mobile applications. I am using Oracle Mobile to build mobile applications that will be used as an extension for Oracle Cloud Products. During my development life-cycle, I discovered a fundamental issue with the Oracle Mobile framework, particularly with the JSONBeanSerializationHelper class.

The role of the JSONBeanSerializationHelper class within the Oracle Mobile framework is to convert JAVA objects to JSON strings. A JSON string is an industry standard accepted for data representation; it consists of name: value pairs. According to the JSON Specification, a JSON String is always case-sensitive. When the JSONBeanSerializationHelper converts a JAVA object into name:value pairs, it doesn’t respect the variable case in the JAVA object. All variables are converted to names in JSON strings in lowercase.

We took this up with Oracle and have an Enhancement Request (ER) logged. We will update this post once the ER has been resolved.

Described below is a use case and how this impacts the mobile application integration with Oracle Service Cloud. However, you could face the same issue when integrating with other Oracle Cloud Products:

Use Case

Consider a use case in which you have a mobile application built using Oracle Mobile. The application has a feature that allows you to create an incident in Oracle Service Cloud.

Steps to reproduce

The following example uses "create incident" API in OSvC to illustrate the issue
  • Define the POJO to represent your payload:
  • public class Incident {
        private Integer id = null;
        private String lookupName = null;
        private String createdTime = null;
        private String updatedTime = null;
        private Asset asset = null;
        private Contact primaryContact = null;
        private String subject = null;
        private Threads threads = null;
        private AssignedTo assignedTo = null;
        private Banner banner = null;
        private String category = null;
        private String channel = null;
        private String chatQueue = null;
        private Date closedTime = null;
        private Account createdByAccount = null;
        private ParentInc ParentInc = null;
        private CustomFields customFields = null;
        private Link[] links;
        private PropertyChangeSupport _propertyChangeSupport = new PropertyChangeSupport(this);
    }
    
    public class CustomFields {
        private Store store;
        private C c;
        private Transit Transit;
        private PropertyChangeSupport _propertyChangeSupport = new PropertyChangeSupport(this);
    }
    
    public class Transit {
        private String Latitude;
        private String Longitude;
        private PropertyChangeSupport _propertyChangeSupport = new PropertyChangeSupport(this);
    }
    
  • The incident object is converted to JSON using the JSONBeanSerializationHelper class
  •   public static Incident convertFromJSON(String response) {
            try {
                incident = (Incident) JSONBeanSerializationHelper.fromJSON(Incident.class, response);
            } catch (Exception e) {
                Debug.print(e.getLocalizedMessage());
            }
            return incident;
        }
  • The converted JSON object:
  • {  
       "updatedTime":{  
          ".null":true
       },
       "createdByAccount":{  
          ".null":true
       },
       "subject":"Curb damaged",
       "customFields":{  
          "c":{  
             "incident_address":"200 East Santa Clara Street San Jose California 95113",
             "incident_zip_postal_code":"95113",
             "incident_state_province":"California",
             "incident_latitude":"37.3378484",
             "incident_city":"San Jose",
             ".type":"com.astcorporation.CRMServiceMobile.api.entities.C",
             "incident_longitude":"-121.8861262",
             "incident_street_address":"200 East Santa Clara Street"
          },
          "transit":{  
             ".type":"com.astcorporation.CRMServiceMobile.api.entities.Transit",
             "latitude":"37.3378484",
             "longitude":"-121.8861262",
             "incidentMappingAddress":"200 East Santa Clara Street San Jose Califo"
          },
          ".type":"com.astcorporation.CRMServiceMobile.api.entities.CustomFields",
          "propertyChangeSupport":{  
             ".type":"oracle.adfmf.java.beans.PropertyChangeSupport",
             "propertyChangeListeners":[  
    
             ]
          },
          "store":{  
             ".null":true
          }
       },
       "channel":{  
          ".null":true
       },
       "threads":{  
          "entryType":{  
             ".type":"com.astcorporation.CRMServiceMobile.api.entities.Entry",
             "id":3
          },
          ".type":"com.astcorporation.CRMServiceMobile.api.entities.Threads",
          "text":"Curb on Ogden & River Road intersection is damaged"
       },
       "banner":{  
          ".null":true
       },
       "propertyChangeSupport":{  
          ".type":"oracle.adfmf.java.beans.PropertyChangeSupport",
          "propertyChangeListeners":[  
    
          ]
       },
       "assignedTo":{  
          ".null":true
       },
       "closedTime":{  
          ".null":true
       },
       "parentInc":{  
          ".null":true
       },
       "chatQueue":{  
          ".null":true
       },
       ".type":"com.astcorporation.CRMServiceMobile.api.entities.Incident",
       "primaryContact":{  
          ".type":"com.astcorporation.CRMServiceMobile.api.entities.Contact",
          "propertyChangeSupport":{  
             ".type":"oracle.adfmf.java.beans.PropertyChangeSupport",
             "propertyChangeListeners":[  
    
             ]
          },
          "id":1847
       },
       "createdTime":{  
          ".null":true
       },
       "links":{  
          ".null":true
       },
       "id":{  
          ".null":true
       },
       "category":{  
          ".null":true
       },
       "asset":{  
          ".null":true
       },
       "lookupName":{  
          ".null":true
       }
    }
    

  • The JSON generated will not be accepted by the create incident API because:
    • It contains “.null” name:value pairs for variables that did not hold any values
    • It contains “.type” name:value pairs for variable with custom data types
    • It contains “propertyChangeSupport” name:value pairs as the beans had a property change attribute defined. This is not expected by the create incident REST-API
    • The JSON did not respect the case of the JAVA variables defined in the Incident bean when generating corresponding name: value pairs. For example: Consider the attribute “transit” in the JSON – the JAVA variable was defined as “Transit”. The create incident REST-API also expects the name to be “Transit”.

Workaround:

  • Option 1: Create your own implementation of the JSON serialization class.
  • Option 2: Create a method to format your converted JSON as a break-fix.
  • Implement the following method removeNullsAndTypeFromJSON post-JSON conversion
    protected static void removeNullsAndTypeFromJSON(JSONObject jsonObj) throws JSONException {
            jsonObj.remove(".type");
            jsonObj.remove("propertyChangeSupport");
    
            for (int i = 0; i < jsonObj.length(); i++) {
                String key = jsonObj.names().getString(i);
                if (JSONBeanSerializationHelper.isObjectNull(jsonObj.get(key))) {
                    jsonObj.remove(key);
                    i--;
                } else {
                    if (jsonObj.get(key).toString().contains(".type")) {
                        removeNullsAndTypeFromJSON(jsonObj.getJSONObject(key));
                    }
                    if (jsonObj.get(key).toString().contains(".null")) {
                        removeNullsAndTypeFromJSON(jsonObj.getJSONObject(key));
                    }
                }
                //BUG: JSONBeanSerializationHelper does not variable match case
                if ("transit".equals(key)) {
                    JSONObject transit = jsonObj.getJSONObject("transit");
                    jsonObj.remove("transit");
                    String Latitude = transit.getString("latitude");
                    transit.remove("latitude");
                    transit.put("Latitude", Latitude);
                    String Longitude = transit.getString("longitude");
                    transit.remove("longitude");
                    transit.put("Longitude", Longitude);
                    String IncidentMappingAddress = transit.getString("incidentMappingAddress");
                    transit.remove("incidentMappingAddress");
                    transit.put("IncidentMappingAddress", IncidentMappingAddress);
                    jsonObj.put("Transit", transit);
                }
            }
    }
    

    Update the convertToJSON method as follows:
    public static JSONObject convertToJSON(Incident incident) {
            try {
                jsonObject = (JSONObject) JSONBeanSerializationHelper.toJSON(incident);
                removeNullsAndTypeFromJSON(jsonObject);
    
            } catch (Exception e) {
                Debug.print(e.getLocalizedMessage());
            }
            return jsonObject;
    }
    




Please share your feedback below. Hope you find this helpful!

CaptiveCode