How to add custom JAR file on Backendless Server Code

Hello Backendless Team -

I’m migrating my app from Parse to Backendless. Thank you for the amazing documentation.

I’m facing an issue with GeoLocation, hope you guys can help me move forward.

My app uses GeoLocation capabilities, I use Google API to find the Geo Location (lat, long) based on the Address user provides and update the same using the Custom Business Logic (JAVA). This API requires custom Jar files like google-maps-services.jar.

Here is the code snippet

@Asset( "Address" )
public class AddressTableEventHandler extends com.backendless.servercode.extension.PersistenceExtender<Address>
{
  @Override
  public void beforeCreate( RunnerContext context, Address address) throws Exception
  {
      LogBuffer.getInstance().setLogReportingPolicy(1, 0);
      Logger logger = Logger.getLogger(AddressTableEventHandler.class);




      String geoAddressString = address.getLines1() + " " + address.getCity() + " " + address.getState() + " " + address.getZip();
      logger.info("geoAddressString is " + geoAddressString);


      GeoApiContext geoContext = new GeoApiContext().setApiKey("....");
      GeocodingResult[] results;


      try {


          results = GeocodingApi.geocode(geoContext, geoAddressString).await();


          GeoPoint geoPoint = new GeoPoint(results[0].geometry.location.lat, results[0].geometry.location.lng);
          geoPoint.addCategory("Address");
          address.setGeolocation(geoPoint);


          logger.info("geoPoint is " + geoPoint);


          Backendless.Data.of(Address.class).save(address, new AsyncCallback<Address>() {


              public void handleResponse(Address address) {
                  //this.logger.info("Handle Address Object Success!!");
                  System.out.println("Handle Address Object Success!!");
              }


              public void handleFault(BackendlessFault backendlessFault) {
                  //this.logger.error("Error Occured while Saving Address", backendlessFault.toString());
                  System.out.println("Handle Address Object Failure!!");
              }
          });


      } catch (Exception e) {
          // TODO Auto-generated catch block
          logger.error("Exception Occured while updating Address", e.fillInStackTrace());
          //System.out.println("Exception Occured while updating Address" + e.getLocalizedMessage());
          e.printStackTrace();
      }
  }
    
}

When i try to test the same using CodeRunner in local, i get the following error message.

Feb 29, 2016 12:41:42 AM com.backendless.coderunner.runtime.task.EventInvocationTask runImpl
SEVERE: Unresolved compilation problems: 
The import com.google cannot be resolved
The import com.google cannot be resolved
The import com.google cannot be resolved
GeoApiContext cannot be resolved to a type
GeoApiContext cannot be resolved to a type
GeocodingResult cannot be resolved to a type
GeocodingApi cannot be resolved


java.lang.Error: Unresolved compilation problems: 
The import com.google cannot be resolved
The import com.google cannot be resolved
The import com.google cannot be resolved
GeoApiContext cannot be resolved to a type
GeoApiContext cannot be resolved to a type
GeocodingResult cannot be resolved to a type
GeocodingApi cannot be resolved


at com.backendless.trackdayshub.events.persistence_service.AddressTableEventHandler.<init>(AddressTableEventHandler.java:15)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
at java.lang.Class.newInstance(Class.java:442)
at com.backendless.coderunner.runtime.task.EventInvocationTask.runImpl(EventInvocationTask.java:72)
at com.backendless.coderunner.runtime.concurrent.ExtendedRunnable.run(ExtendedRunnable.java:22)
at java.lang.Thread.run(Thread.java:745)

I pushed the changes to Production using the Deploy.sh script, i see the new Class file and JAR files under lib directory but I dont see this piece of code getting executed.

Can you please advice?

Hi Arasan,

Do you know if Google APIs can work in server-side code?

Did you place all the dependencies in the /libs folder per the CodeRunner requirement?

Have you tried to debug it locally to make sure everything works before deploying the code to production?

Mark

Hi Mark -

My responses below…

Do you know if Google APIs can work in server-side code? [AR] - I’m hoping it should work. Can you please confirm if API calls to google will work on Server-Side? If not, can you please let me know what other options i have to find the GeoPoint to update my Backendless table.

Did you place all the dependencies in the /libs folder per the CodeRunner requirement? [AR] - Yes, i did.

Have you tried to debug it locally to make sure everything works before deploying the code to production? [AR] - It dint work locally, i have attached the logs i received while testing the code locally.

It looks like the errors you received are coming from the google libraries. I would recommend creating a basis command line Java program and get your algorithm to work there. Once you know what the minimum required set of jar files is, then you should move on to CodeRunner.

Hi Mark -

Thank you for the quick responses!

I got those issues fixed with the libraries. Looks like my IDE’s dint compile the java files correctly causing the above errors. I have fixed them but have a different error while executing. Can you please advice?

java.security.AccessControlException: You have no permission to thread manipulation
at com.backendless.coderunner.runtime.security.CodeRunnerSecurityManager.getThreadGroup(CodeRunnerSecurityManager.java:34)
at java.lang.Thread.init(Thread.java:379)
at java.lang.Thread.init(Thread.java:349)
at java.lang.Thread.<init>(Thread.java:461)
at com.google.maps.internal.RateLimitExecutorService.<init>(RateLimitExecutorService.java:60)
at com.google.maps.GeoApiContext.<init>(GeoApiContext.java:58)
at com.backendless.testapp.events.persistence_service.AddressTableEventHandler.beforeCreate(AddressTableEventHandler.java:47)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.backendless.coderunner.runtime.task.EventInvocationTask.runImpl(EventInvocationTask.java:92)
at com.backendless.coderunner.runtime.concurrent.ExtendedRunnable.run(ExtendedRunnable.java:22)
at java.lang.Thread.run(Thread.java:745)

This error indicates that you’re attempting to create a thread in your code (either directly or indirectly) which is not allowed in custom business logic.