0

I am trying to use MaxMind GeoIP2 on Google App Engine. Locally it works, but when I deploy it on GAE I get an error because of a restricted class

java.lang.NoClassDefFoundError: java.nio.MappedByteBuffer is a restricted class. Please see the Google App Engine developer's guide for more details.
    at java.nio.channels.FileChannel.map(FileChannel.java)
    at com.maxmind.db.BufferHolder.<init>(BufferHolder.java:31)
    at com.maxmind.db.Reader.<init>(Reader.java:116)
    at com.maxmind.geoip2.DatabaseReader.<init>(DatabaseReader.java:39)
    at com.maxmind.geoip2.DatabaseReader.<init>(DatabaseReader.java:27)
    at com.maxmind.geoip2.DatabaseReader$Builder.build(DatabaseReader.java:133)

Is there any "trick", like using a particular version of GeoIP2, that will not use this error ? I use version 2.7.0 via gradle

compile group: "com.maxmind.geoip2", name: "geoip2", version: "2.7.0"

Anybody tried with legacy version of GeoIP ? Any luck there ? My only aim is to understand how to use this library, if possible, or to find an alternative one that offers the same capability (obtaining ISO code of the country from the IP)

Ing. Luca Stucchi
  • 3,070
  • 6
  • 36
  • 58
  • Possible duplicate of [NoClassDefFoundError when adding new font in iText on AppEngine](http://stackoverflow.com/questions/19392184/noclassdeffounderror-when-adding-new-font-in-itext-on-appengine) – sidgate Apr 28 '16 at 10:00
  • Thanks @sidgate yes it's pretty obvious where the problem is (the class java.nio.MappedByteBuffer can't be used) but since I'd like to use GeoIP library I was asking if anybody sorted out how to do is already (if possible). – Ing. Luca Stucchi Apr 28 '16 at 10:11

3 Answers3

2

You should be able to use the memory mode in GeoIP2 on GAE instead:

DatabaseReader reader = new DatabaseReader.Builder(dbFile)
         .fileMode(Reader.FileMode.MEMORY).build();
Greg Oschwald
  • 1,716
  • 2
  • 11
  • 14
  • Interesting, but this would mean that my server will allocate all the memory to basically cache everything, isn't it ? In that case, I fear that I simply can't afford that since I use small instances and it wouldn't be wise to eat up so much memory. – Ing. Luca Stucchi May 10 '16 at 11:17
  • Yes, that is correct, but for a GeoLite2 Country database, this amounts to 2.3 MB. – Greg Oschwald May 10 '16 at 15:01
1

GAE supplies this in a request header to your app:

String visitorCountry = request.getHeader("X-AppEngine-Country");

Note that it may be empty on the dev server, but populated when deployed.

Mark Doyle
  • 4,804
  • 3
  • 20
  • 23
0

If GeoIP2 can't be deployed on GAE, I found out that GeoIP Legacy can, and in particular I set in gradle:

compile group: "com.maxmind.geoip", name: "geoip-api", version: "1.3.1"

With the associated GeoIP.dat file that can be downloaded here

This version runs on GAE without any problem

Ing. Luca Stucchi
  • 3,070
  • 6
  • 36
  • 58
  • Yes, thanks, I tried to follow this path, but what about the accuracy of the database ? I had pretty bad results, unfortunately, like half of Europe seemed to be in China ! :( Did you make some attempts to verify the accuracy ? – Ing. Luca Stucchi May 10 '16 at 11:14