6.0 java business logic API jar file breaks code

Hi,

Before the 6.0 update, I had a java API call to find and update records in a table that worked fine. I tried the same code after the 6.0 update and it no longer updates my records. It will create records, but will not update any existing records.

Before putting in a ticket to request help. I wanted to download the latest Java API Backendless jar file, put it into my project, rebuild and see if the newer jar file would change the situation. It did not. In fact, I can no longer run the API at all. Here is what I get when I try to do a CodeRunner debug mode:

I see an error message regarding “com.backendless.servercode.extension.MediaExtender”

Please help me understand how to:

  1. Get the latest jar file to work in a pre-6.0 project
  2. Get the update to a record to actually update.

Thanks,

Mark

FYI, I put the older jar file back in place, the project compiles, and here is the failed update log

The log shows:

  1. Find a record
  2. Display record before update “UsageCount=1”
  3. Update the value in the object “UsageCount=2”
  4. Display results after save “UsageCount=1”

The database also reflects that the UsageCount value is still 1

Let’s make sure you have the latest CodeRunner and Backendless jar. In the first screenshot you shared, it says:

Version 5.7.3.2.cloud

which is not the latest. To download the latest, please do the following:

  1. Could you please login to Backendless Console
  2. Switch to the Business Logic screen
  3. Select the CODING tab
  4. Select JAVA
  5. Click the blue download icon.

This will download not only CodeRunner and backendless jar, but the deployed code as well. Make sure to get the /bin directory and the backendless.jar from the downloaded zip and update in your installation.

Please let me know if you can get a successful deployment after that.

Regards,
Mark

I’ve got the updated /bin folder and /lib/backendless.jar file, here’s the logfile from an attempt to run CodeRunner.sh

/Users/mark/Projects/Customer_Support_Backendless_API/bin/CodeRunner.sh
Path to “JAVA_HOME”: /Library/Java/JavaVirtualMachines/jdk-14.0.1.jdk/Contents/Home
Running CodeRunner …
env JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-14.0.1.jdk/Contents/Home /Library/Java/JavaVirtualMachines/jdk-14.0.1.jdk/Contents/Home/bin/java -XX:-OmitStackTraceInFastThrow -XX:+HeapDumpOnOutOfMemoryError -server -Xms384m -Xmx768m -Duser.timezone=UTC -Dfile.encoding=UTF-8 -Djava.net.preferIPv4Stack=true -Dlogback.configurationFile=logback.xml --add-modules java.se --add-exports java.base/jdk.internal.ref=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.nio=ALL-UNNAMED --add-opens java.base/sun.nio.ch=ALL-UNNAMED --add-opens java.management/sun.management=ALL-UNNAMED --add-opens jdk.management/com.sun.management.internal=ALL-UNNAMED -Dcom.sun.management.jmxremote.port=1097 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=backendless-dev.local -cp “:…/libs/” com.backendless.coderunner.CodeRunnerLoader
19:59:08.814 [INFO] c.b.c.CodeRunnerLoader |main| JDK from “JAVA_HOME” - /Library/Java/JavaVirtualMachines/jdk-14.0.1.jdk/Contents/Home
19:59:08.831 [INFO] c.b.c.CommandLineProcessor |main| CodeRunner™ Backendless Debugging Utility
19:59:08.831 [INFO] c.b.c.CommandLineProcessor |main| Copyright(C) 2020 Backendless Corp. All rights reserved.
19:59:08.832 [INFO] c.b.c.CommandLineProcessor |main| Build date: 2020-06-26T12:07:16Z
Version: 6.0.0.12
Build id: 196289
VCS revision: 9738d883a43a98b7860144c59b8938fdd861f672
19:59:08.833 [INFO] c.b.c.CommandLineProcessor |main| CodeRunner session is running for 2 hours and will be terminated on 21:59:08.833308[UTC]
19:59:08.874 [INFO] c.b.h.HealthCheckHttpServer |main| Management port is absent, management server not started
19:59:08.875 [INFO] c.b.coderunner.LocalCodeRunner |main| Registering runner on: ‘https://api.backendless.com
19:59:08.876 [INFO] c.b.coderunner.LocalCodeRunner |main| Application ID: ‘5571A518-B5D9-43D0-8B58-D285A3CE1E74’
19:59:08.877 [INFO] c.b.coderunner.LocalCodeRunner |main| Api key: ‘5E4861F1-8132-4538-936D-69718270FF57’
19:59:11.681 [INFO] c.b.coderunner.LocalCodeRunner |main| Runner successfully registered
19:59:11.689 [INFO] c.b.c.parser.EventModelParser |main| Parsing event model…
19:59:12.091 [ERROR] c.b.c.runtime.ServiceParser |main| Error while parsing jar file …/libs/backendless.jar.new.jar. android/webkit/WebViewClient
java.lang.NoClassDefFoundError: android/webkit/WebViewClient
at java.base/java.lang.ClassLoader.defineClass1(Native Method)
at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1017)
at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:151)
at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:821)
at java.base/jdk.internal.loader.BuiltinClassLoader$4.run(BuiltinClassLoader.java:732)
at java.base/jdk.internal.loader.BuiltinClassLoader$4.run(BuiltinClassLoader.java:727)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:312)
at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:740)
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:642)
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:600)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:576)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
at com.backendless.coderunner.runtime.ServiceParser.checkAndAddClasss(ServiceParser.java:136)
at com.backendless.coderunner.runtime.ServiceParser.findServiceClassesInLibs(ServiceParser.java:78)
at com.backendless.coderunner.runtime.task.CustomServiceParserTask.parse(CustomServiceParserTask.java:85)
at com.backendless.coderunner.parser.DebugHostedServiceParser.parseServiceModel(DebugHostedServiceParser.java:31)
at com.backendless.coderunner.debugger.BusinessLogicDebugger.build(BusinessLogicDebugger.java:53)
at com.backendless.coderunner.debugger.InstructionsFetcher.executeCommandSafe(InstructionsFetcher.java:30)
at com.backendless.coderunner.LocalCodeRunner.listenForServiceMessages(LocalCodeRunner.java:74)
at com.backendless.coderunner.CodeRunnerLoader.launch(CodeRunnerLoader.java:42)
at com.backendless.coderunner.CodeRunnerLoader.main(CodeRunnerLoader.java:29)
Caused by: java.lang.ClassNotFoundException: android.webkit.WebViewClient
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:602)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
… 22 common frames omitted
19:59:12.093 [ERROR] c.b.c.runtime.ServiceParser |main| Error while parsing jar file …/libs/backendless.jar.old.jar. android/os/Handler$Callback
java.lang.NoClassDefFoundError: android/os/Handler$Callback
at java.base/java.lang.ClassLoader.defineClass1(Native Method)
at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1017)
at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:151)
at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:821)
at java.base/jdk.internal.loader.BuiltinClassLoader$4.run(BuiltinClassLoader.java:732)
at java.base/jdk.internal.loader.BuiltinClassLoader$4.run(BuiltinClassLoader.java:727)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:312)
at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:740)
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:642)
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:600)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:576)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
at com.backendless.coderunner.runtime.ServiceParser.checkAndAddClasss(ServiceParser.java:136)
at com.backendless.coderunner.runtime.ServiceParser.findServiceClassesInLibs(ServiceParser.java:78)
at com.backendless.coderunner.runtime.task.CustomServiceParserTask.parse(CustomServiceParserTask.java:85)
at com.backendless.coderunner.parser.DebugHostedServiceParser.parseServiceModel(DebugHostedServiceParser.java:31)
at com.backendless.coderunner.debugger.BusinessLogicDebugger.build(BusinessLogicDebugger.java:53)
at com.backendless.coderunner.debugger.InstructionsFetcher.executeCommandSafe(InstructionsFetcher.java:30)
at com.backendless.coderunner.LocalCodeRunner.listenForServiceMessages(LocalCodeRunner.java:74)
at com.backendless.coderunner.CodeRunnerLoader.launch(CodeRunnerLoader.java:42)
at com.backendless.coderunner.CodeRunnerLoader.main(CodeRunnerLoader.java:29)
Caused by: java.lang.ClassNotFoundException: android.os.Handler$Callback
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:602)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
… 22 common frames omitted
19:59:12.097 [INFO] c.b.c.r.t.CustomServiceParserTask |main| Run dependency analyzer for app: 5571A518-B5D9-43D0-8B58-D285A3CE1E74
ClassPath: /Users/mark/Projects/Customer_Support_Backendless_API/libs/backendless.jar.new.jar:/Users/mark/Projects/Customer_Support_Backendless_API/libs/servlet-api-2.5.jar:/Users/mark/Projects/Customer_Support_Backendless_API/libs/backendless.jar.old.jar:/Users/mark/Projects/Customer_Support_Backendless_API/libs/backendless.jar
19:59:12.097 [INFO] DependencyAnalyzer |main| Analyze service: us.boundlessdesign.customersupport.services.MobileService
19:59:12.179 [INFO] DependencyAnalyzer |main| Analyze service: us.boundlessdesign.customersupport.services.ManagementService
19:59:12.316 [INFO] c.b.c.d.DebuggerConsoleInterface |main| Build successfully: 0 event handlers and 0 timers and 2 services
19:59:12.317 [INFO] c.b.c.d.DebuggerConsoleInterface |main| Deploying model to server, and starting debug…
19:59:13.105 [INFO] c.b.c.d.DebuggerConsoleInterface |main| Model successfully deployed.
19:59:13.106 [INFO] c.b.c.d.DebuggerConsoleInterface |main| Waiting for events…

This does not look right:

Do you have a file named backendless.jar.new.jar in the /libs folder?

Sorry, i had copied the older jar files to “.new” and “.old”. I removed those and here is the log now:

/Users/mark/Projects/Customer_Support_Backendless_API/bin/CodeRunner.sh
Path to “JAVA_HOME”: /Library/Java/JavaVirtualMachines/jdk-14.0.1.jdk/Contents/Home
Running CodeRunner …
env JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-14.0.1.jdk/Contents/Home /Library/Java/JavaVirtualMachines/jdk-14.0.1.jdk/Contents/Home/bin/java -XX:-OmitStackTraceInFastThrow -XX:+HeapDumpOnOutOfMemoryError -server -Xms384m -Xmx768m -Duser.timezone=UTC -Dfile.encoding=UTF-8 -Djava.net.preferIPv4Stack=true -Dlogback.configurationFile=logback.xml --add-modules java.se --add-exports java.base/jdk.internal.ref=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.nio=ALL-UNNAMED --add-opens java.base/sun.nio.ch=ALL-UNNAMED --add-opens java.management/sun.management=ALL-UNNAMED --add-opens jdk.management/com.sun.management.internal=ALL-UNNAMED -Dcom.sun.management.jmxremote.port=1097 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=backendless-dev.local -cp “:…/libs/” com.backendless.coderunner.CodeRunnerLoader
20:04:19.091 [INFO] c.b.c.CodeRunnerLoader |main| JDK from “JAVA_HOME” - /Library/Java/JavaVirtualMachines/jdk-14.0.1.jdk/Contents/Home
20:04:19.103 [INFO] c.b.c.CommandLineProcessor |main| CodeRunner™ Backendless Debugging Utility
20:04:19.103 [INFO] c.b.c.CommandLineProcessor |main| Copyright(C) 2020 Backendless Corp. All rights reserved.
20:04:19.104 [INFO] c.b.c.CommandLineProcessor |main| Build date: 2020-06-26T12:07:16Z
Version: 6.0.0.12
Build id: 196289
VCS revision: 9738d883a43a98b7860144c59b8938fdd861f672
20:04:19.105 [INFO] c.b.c.CommandLineProcessor |main| CodeRunner session is running for 2 hours and will be terminated on 22:04:19.104798[UTC]
20:04:19.142 [INFO] c.b.h.HealthCheckHttpServer |main| Management port is absent, management server not started
20:04:19.142 [INFO] c.b.coderunner.LocalCodeRunner |main| Registering runner on: ‘https://api.backendless.com
20:04:19.144 [INFO] c.b.coderunner.LocalCodeRunner |main| Application ID: ‘5571A518-B5D9-43D0-8B58-D285A3CE1E74’
20:04:19.144 [INFO] c.b.coderunner.LocalCodeRunner |main| Api key: ‘5E4861F1-8132-4538-936D-69718270FF57’
20:04:21.869 [INFO] c.b.coderunner.LocalCodeRunner |main| Runner successfully registered
20:04:21.878 [INFO] c.b.c.parser.EventModelParser |main| Parsing event model…
20:04:22.394 [INFO] c.b.c.r.t.CustomServiceParserTask |main| Run dependency analyzer for app: 5571A518-B5D9-43D0-8B58-D285A3CE1E74
ClassPath: /Users/mark/Projects/Customer_Support_Backendless_API/libs/servlet-api-2.5.jar:/Users/mark/Projects/Customer_Support_Backendless_API/libs/backendless.jar
20:04:22.395 [INFO] DependencyAnalyzer |main| Analyze service: us.boundlessdesign.customersupport.services.MobileService
20:04:22.517 [INFO] DependencyAnalyzer |main| Analyze service: us.boundlessdesign.customersupport.services.ManagementService
20:04:22.689 [INFO] c.b.c.d.DebuggerConsoleInterface |main| Build successfully: 0 event handlers and 0 timers and 2 services
20:04:22.690 [INFO] c.b.c.d.DebuggerConsoleInterface |main| Deploying model to server, and starting debug…
20:04:23.538 [INFO] c.b.c.d.DebuggerConsoleInterface |main| Model successfully deployed.
20:04:23.539 [INFO] c.b.c.d.DebuggerConsoleInterface |main| Waiting for events…

here’s the log from an attempt to udpate an existing record (Showing the update doesn’t actually save to the DB):

searching for? C03DA130-3CD2-DE6A-FF92-FA7CAC346D00
records found 3
existing record? Optional[DeviceUsage{Id=‘1CA2F9B8-53ED-755F-FF54-E95EB76D8300’, DeviceId=‘180A921F-781C-4C2B-81CA-9981F14FB2C1’, MobileDeviceId=‘C03DA130-3CD2-DE6A-FF92-FA7CAC346D00’, UsageCount=1}]
Before update existing Device Usage DeviceUsage{Id=‘1CA2F9B8-53ED-755F-FF54-E95EB76D8300’, DeviceId=‘180A921F-781C-4C2B-81CA-9981F14FB2C1’, MobileDeviceId=‘C03DA130-3CD2-DE6A-FF92-FA7CAC346D00’, UsageCount=1}
After update existing Device Usage DeviceUsage{Id=‘1CA2F9B8-53ED-755F-FF54-E95EB76D8300’, DeviceId=‘180A921F-781C-4C2B-81CA-9981F14FB2C1’, MobileDeviceId=‘C03DA130-3CD2-DE6A-FF92-FA7CAC346D00’, UsageCount=2}
Before Insert/Update Device Usage DeviceUsage{Id=‘1CA2F9B8-53ED-755F-FF54-E95EB76D8300’, DeviceId=‘180A921F-781C-4C2B-81CA-9981F14FB2C1’, MobileDeviceId=‘C03DA130-3CD2-DE6A-FF92-FA7CAC346D00’, UsageCount=2}
Device Saved:DeviceUsage{Id=‘1CA2F9B8-53ED-755F-FF54-E95EB76D8300’, DeviceId=‘180A921F-781C-4C2B-81CA-9981F14FB2C1’, MobileDeviceId=‘C03DA130-3CD2-DE6A-FF92-FA7CAC346D00’, UsageCount=1}

Here is the code that does the actual DB save:

Does the class of record object have the objectId public field or public getObjectId()/setObjectId(String) methods?

objectId field is private. There is a getObjectId() method, but no setter. Which do I need to do: Change to public field, or add setObjectId(String) method?

Also, was this an expected breaking change for 6.0?

Either one should do it. I do not quite understand how why it worked before. When the field is private and there is no setObjectId(String) method, the object would not be getting the objectId value assigned since there is no way to assign it.

Neither worked. Here is the POJO. It has the default constructor, it has the private property and the get/set methods. I tested the other way as well with the public property. I can DM you the source code of the whole API service if you’d like

package us.boundlessdesign.customersupport.models;
import weborb.service.MapToProperty;
public class DeviceUsage {
@MapToProperty(property = “objectId”)
private String objectId;
@MapToProperty(property = “deviceid”)
private String DeviceId;
@MapToProperty(property = “mobiledeviceid”)
private String MobileDeviceId;
@MapToProperty(property = “usagecount”)
private Integer UsageCount;
public DeviceUsage() {
}
public String getObjectId() {
return objectId;
}
public void setObjectId(String objectId) {
this.objectId = objectId;
}
public String getDeviceId() {
return DeviceId;
}
public void setDeviceId(String deviceId) {
DeviceId = deviceId;
}
public String getMobileDeviceId() {
return MobileDeviceId;
}
public void setMobileDeviceId(String mobileDeviceId) {
MobileDeviceId = mobileDeviceId;
}
public Integer getUsageCount() {
return UsageCount;
}
public void setUsageCount(Integer usageCount) {
UsageCount = usageCount;
}
@Override
public String toString() {
return “DeviceUsage{” +
“Id='” + objectId + ‘'’ +
“, DeviceId='” + DeviceId + ‘'’ +
“, MobileDeviceId='” + MobileDeviceId + ‘'’ +
“, UsageCount=” + UsageCount +
‘}’;
}
}

What makes you think the object is not saved? It is not clear to me what property is modified after the object is retrieved and what you’re checking. Please elaborate.

Regards,
Mark

The UsageCount property needs to update from 1 to 2. The log shows the record with the objectId = ‘1CA2F9B8-53ED-755F-FF54-E95EB76D8300’ should have the UsageCount value of 1 when it is pulled from the database, then it is incremented to 2, then it should be saved. But after the save, it the returned object still has a UsageCount = 1. Also when looking at it from the Console, it has updated timestamp, but it does not have a changed UsageCount value.

To double check my own sanity, there are other records that have incremented UsageCount values, but not since the 6.0 upgrade.

Could you try (as a test, I need your help in figuring out where it misfires), make the following changes in the DeviceUsage class:

  1. Rename the UsageCount field to:
    private Integer usagecount;
    
  2. Remove the following line:
    @MapToProperty(property = “usagecount”)
    
  3. rename get/set methods:
    public void setusagecount(Integer usageCount) 
    public Integer getusagecount()
    

Please let me know if it gets updated after these changes

Regards,
Mark

Yes, this worked. Does this mean the weborb MapToProperty functionality is not supported anymore? Or possibly there is another change that would allow me to have my property names be different than the DB?

Thanks,

Mark

It should still be supported, but apparently something is not working quite right. This gives us enough information to know where to dig and I am thankful to you for that. I am opening an internal ticket for investigation. We will notify you when it is fixed.

Regards,
Mark

Internal ticket # is BKNDLSS-22105

Thanks much!

Here’s some more information. I turned off all weborb mappings and set the POJO properties to match the DB column names exactly. When I attempt an update, I now see it creating a second record, and it has a higher usagecount value

Here’s the class

And here’s a picture of the records, where is shows identical rows, except usagecount is different.

Hope this adds more light to the weborb mapping issue and a resolution comes soon.

Thanks,
Mark

Make sure to rename objectid to objectId and the methods to getObjectId() and setObjectId( String ).

Regards,
Mark