Uploaded image for project: 'PUBLIC - Liferay Portal Community Edition'
  1. PUBLIC - Liferay Portal Community Edition
  2. LPS-54220

Cannot pass custom objects to a BackgroundTaskExecutor via taskContextMap

    Details

      Description

      I am using the BackgroundTask framework to run tasks from a portlet plugin context.
      I pass objects whose classes are in plugin portlet as parameters to my class extending BaseBackgroundTaskExecutor via the taskContextMap variable.
      When executing the task, a ClassNotFoundException is thrown, since the deserialization of the taskContextMap content happens in the portal servlet context, while I expected it to run in the servlet context specified when calling BackgroundTaskLocalServiceUtil.addBackgroundTask().

      Attached are a plugin with a portlet that recreates the problem, a war created from it and the stack trace.

      Best regards
      Tommaso

      Reproduction Steps:
      1) deploy test-background-task-1.0.0-SNAPSHOT.war
      2) add the test-background-task portlet to a page
      3) click on it's button

      Expected results:
      The background-task should run without errors

      Actual Results: The following error is displayed in the console:

      14:21:47,716 ERROR [liferay/background_task-1][BackgroundTaskMessageListener:133] Unable to execute background task
      java.lang.IllegalStateException: Unable to deserialize object
      	at com.liferay.portal.json.JSONFactoryImpl.deserialize(JSONFactoryImpl.java:183)
      	at com.liferay.portal.kernel.json.JSONFactoryUtil.deserialize(JSONFactoryUtil.java:80)
      	at com.liferay.portal.model.impl.BackgroundTaskImpl.getTaskContextMap(BackgroundTaskImpl.java:161)
      	at com.example.MyBackgroundTaskExecutor.execute(MyBackgroundTaskExecutor.java:20)
      	at com.liferay.portal.kernel.backgroundtask.ClassLoaderAwareBackgroundTaskExecutor.execute(ClassLoaderAwareBackgroundTaskExecutor.java:50)
      	at com.liferay.portal.backgroundtask.messaging.BackgroundTaskMessageListener.doReceive(BackgroundTaskMessageListener.java:108)
      	at com.liferay.portal.kernel.messaging.BaseMessageListener.receive(BaseMessageListener.java:26)
      	at com.liferay.portal.kernel.messaging.InvokerMessageListener.receive(InvokerMessageListener.java:72)
      	at com.liferay.portal.kernel.messaging.ParallelDestination$1.run(ParallelDestination.java:69)
      	at com.liferay.portal.kernel.concurrent.ThreadPoolExecutor$WorkerTask._runTask(ThreadPoolExecutor.java:682)
      	at com.liferay.portal.kernel.concurrent.ThreadPoolExecutor$WorkerTask.run(ThreadPoolExecutor.java:593)
      	at java.lang.Thread.run(Unknown Source)
      Caused by: org.jabsorb.serializer.UnmarshallException: key params Class specified in javaClass hint not found: com.example.BackgroundTaskParams
      	at org.jabsorb.serializer.impl.MapSerializer.unmarshall(MapSerializer.java:270)
      	at org.jabsorb.JSONSerializer.unmarshall(JSONSerializer.java:692)
      	at com.liferay.portal.json.jabsorb.serializer.LiferayJSONSerializer.unmarshall(LiferayJSONSerializer.java:50)
      	at org.jabsorb.JSONSerializer.fromJSON(JSONSerializer.java:262)
      	at com.liferay.portal.json.JSONFactoryImpl.deserialize(JSONFactoryImpl.java:176)
      	... 11 more
      Caused by: org.jabsorb.serializer.UnmarshallException: Class specified in javaClass hint not found: com.example.BackgroundTaskParams
      	at org.jabsorb.JSONSerializer.getClassFromHint(JSONSerializer.java:748)
      	at org.jabsorb.JSONSerializer.unmarshall(JSONSerializer.java:672)
      	at com.liferay.portal.json.jabsorb.serializer.LiferayJSONSerializer.unmarshall(LiferayJSONSerializer.java:50)
      	at org.jabsorb.serializer.impl.MapSerializer.unmarshall(MapSerializer.java:265)
      	... 15 more
      Caused by: java.lang.ClassNotFoundException: com.example.BackgroundTaskParams
      	at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1714)
      	at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1559)
      	at java.lang.Class.forName0(Native Method)
      	at java.lang.Class.forName(Unknown Source)
      	at org.jabsorb.JSONSerializer.getClassFromHint(JSONSerializer.java:744)
      	... 18 more
      

      Reproduced on Master (b186cdf2ba338364d7a80d6a2f096b993df36eeb)


      Technical Analysis

      The problem is not exactly this: "since the deserialization of the taskContextMap content happens in the portal servlet contex"
      The deserialization happens in the webapp context however JSONSerializer.getClassFromHint(Object o) calls Class.forName(String).

      Class.forName(String className) Javadoc
      public static Class<?> forName(String className) throws ClassNotFoundException
      Returns the Class object associated with the class or interface with the given string name. Invoking this method is equivalent to:
            Class.forName(className, true, currentLoader)
      
      where currentLoader denotes the defining class loader of the current class.
      

      That will look for BackgroundTaskParams on the wrong classloader.

      Additional info:
      Source for jabsorb can be found here: https://repo1.maven.org/maven2/org/jabsorb/jabsorb/1.3.2/
      or here: https://code.google.com/archive/p/jabsorb/

      As Google code is not maintained anymore I think we should use the maven repository, but in that case we have to upgrade to 1.3.2 as the current version we use(1.3.1) is not available there.


      Testing Notes
      Use test-background-task-1.0.0-SNAPSHOT-fixed.war when testing the solution, because he custom class (com.example.BackgroundTaskParams) had to be updated to have a public nor-arg constructor in order to make serialization work.


      About Master/7.0:
      The type of taskContextMap was changed to Map in hibernate by LPS-45869. This makes effectively impossible to use classes in taskContextMap which are not visible to BackgroundTask module's classloader, as BackgroundTaskPersistence will try to deserialize the map on updates as we always call session.merge.
      Requires a unique fix.
      See: LPS-65306

        Attachments

          Issue Links

            Activity

              People

              • Votes:
                4 Vote for this issue
                Watchers:
                3 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved:
                  Days since last comment:
                  3 years, 27 weeks, 5 days ago

                  Packages

                  Version Package
                  6.2.X EE