Giter Site home page Giter Site logo

sybit-education / airtable.java Goto Github PK

View Code? Open in Web Editor NEW
46.0 13.0 25.0 9.7 MB

Java API for Airtable (http://www.airtable.com)

License: MIT License

Java 100.00%
airtable java api-client java-api crud airtable-api airtable-client hacktoberfest hacktoberfest2022 hacktoberfest2023

airtable.java's Introduction

Airtable.java - The Java API for Airtable

Codacy Badge Codacy Badge license

This is a Java API client for Airtable (http://www.airtable.com).

The Airtable API provides a simple way of accessing data within Java projects.

More information about the Airtable API could be found at https://airtable.com/api. The documentation will provide detailed information about your created base.

Usage

For adding dependency, you could use bintray-repository: https://bintray.com/sybit-education/maven/airtable.java

The files are stored at: https://dl.bintray.com/sybit-education/maven/

Gradle

For Gradle add compile com.sybit:airtable.java:[version] to compile dependencies. Also add repository to dependencies:

repositories {
  maven {
    url = uri("https://maven.pkg.github.com/Sybit-Education/airtable.java")
    ...
  }
}

Initializing

It is required to initialize the Java API before it is used. At leased you have to pass your API-Key to get access to Airtable:

Airtable airtable = new Airtable().configure();

API-Key

The API key could be passed to the app in different ways:

  • Defining Java property AIRTABLE_API_KEY (e.g. -DAIRTABLE_API_KEY=foo).
  • Defining OS environment variable AIRTABLE_API_KEY (e.g. export AIRTABLE_API_KEY=foo).
  • Defining property file credentials.properties in root classpath containing key/value AIRTABLE_API_KEY=foo.
  • On the other hand the API-key could also be added by using the method Airtable.configure(String apiKey).

How to get API-Key

See: https://support.airtable.com/hc/en-us/articles/219046777-How-do-I-get-my-API-key-

Proxy Support

The API supports environment variable http_proxy. If the variable is set, it is used automatically.

  • On Windows: set http_proxy=http://your_proxy:your_port
  • On Unix/OS X: export http_proxy=http://your_proxy:your_port

If endpointUrl contains localhost or 127.0.0.1 proxy settings are ignored automatically.

Logging

The Simple Logging Facade for Java SLF4J serves as a simple facade or abstraction for various logging frameworks (e.g. java.util.logging, logback, log4j) allowing the end user to plug in the desired logging framework at deployment time.

Request Limits

The API of Airtable itself is limited to 5 requests per second. If you exceed this rate, you will receive a 429 status code and will need to wait 30 seconds before subsequent requests will succeed.

Connecting to Airtable

To use this libraray you will need an Airtable object. Simply create one: Airtable airtable = new Airtable();. This object needs an API-Key or it won't work properly so airtable.configure(AIRTABLE_API_KEY);. Now the Airtable object needs to know which base you want to access. This method will return a Base object which will be used in the future: Base base = airtable.base(AIRTABLE_BASE);

With the Base object you can perform all kind of operations see more at CRUD Operations on Table Records.

Object Mapping

The Java implementation of the Airtable API provides automatic object mapping. You can map any table to your own Java classes. But first you need to specify those classes.

Create a Object

The Java objects represent records or 'values' in Airtable. So the class attributes need to be adjusted to the Airtable Base.

Example

In Airtable we got a table 'Actor'. The columns represent the class attributes.

This is how our 'Actor' table looks like:

Index Name Photo Biography Filmography
1 Marlon Brando Some Photos Long Text Reference to the Movie Table
2 Bill Murray Some Photos Long Text Reference to the Movie Table
3 Al Pacino Some Photos Long Text Reference to the Movie Table
... ... ... ... ...

Now our Java class should look like this:

  public class Actor {

      private String id;
      @SerializedName("Name")
      private String name;
      @SerializedName("Photo")
      private List<Attachment> photo;
      @SerializedName("Biography")
      private String biography;
      @SerializedName("Filmography")
      private String[] filmography;

      public String getId() {
          return id;
      }

      public void setId(String id) {
          this.id = id;
      }

      public String getName() {
          return name;
      }

      public void setName(String name) {
          this.name = name;
      }

      public String[] getFilmography() {
          return filmography;
      }

      public void setFilmography(String[] filmography) {
          this.filmography = filmography;
      }

      public List<Attachment> getPhoto() {
          return photo;
      }

      public void setPhoto(List<Attachment> photo) {
          this.photo = photo;
      }

      public String getBiography() {
          return biography;
      }

      public void setBiography(String biography) {
          this.biography = biography;
      }
  }

For each column we give the Java class an attribute with the column name (Be careful! See more about naming in the Section Annotations) and add Getters and Setters for each attribute. The attribute types can be either primitive Java types like String and Float for Text and Numbers, String Array for references on other Tables or Attachment for attached photos and files.

Now we got everything we need to create our first Airtable table object. We use the Java class we just wrote to specify what kind of Object should be saved in our table. Then we tell our base-object which table we want to access. All the records saved in our Airtable Base now should be in our local Table Object.

Example:

Base base = airtable.base('AIRTABLE_API_KEY');
Table<JAVA CLASS> actorTable = base.table("NAME OF THE TABLE", <JAVA_CLASS>);
//Example with the Actor Table
Table<Actor> actorTable = base.table("Actors", Actor.class);

Basic Objects

The Java implementation of the Airtable-API provides an implementation of basic Airtable objects such as attachments and thumbnails.
Photos and attached files in Airtable are retrieved as Attachments. Photos furthermore contain Thumbnail-Objects for different sizes.

Attachment

All the Attachment-objects got the following attributes:

  • String id
  • String url
  • String filename
  • Float size
  • String type

Photos additionally have:

  • Map<String,Thumbnail> thumbnails

Thumbnails

A Thumbnail is generated for image files in Airtable. Thumbnails are bound to an Attachment-object as a key/value Map. The keys are small and large for the different sizes. The value is a Thumbnail-object.

A Thumbnail-object got the following Attributes:

  • String name
  • String url
  • Float width
  • Float height

Note: The name of a Thumbnail Object is identical with it´s key ( small or large ).

Annotations

Use the annotation @SerializedName of Gson to annotate column names containing -, empty characters or other not in Java mappable characters. The airtable.java API will respect these mappings automatically.

Example

import com.google.gson.annotations.SerializedName;

//Column in Airtable is named "First- & Lastname", which is mapped to field "name".
@SerializedName("First- & Lastname")
private String name;

Sort

With the integrated Sort element you can retrieve a list of sorted objects that specifies how the records will be ordered. Each sort object must have a field key specifying the name of the field to sort on, and an optional direction key that is either "asc" or "desc". The default direction is "asc".

For example, to sort records by Name, pass in:

Sort sort = new Sort("Name", Sort.Direction.desc);
List<Movie> listMovies = movieTable.select(sort);

If you set the view parameter, the returned records in that view will be sorted by these fields.

Detailed example see TableParameterTest

CRUD-Operations on Table Records

Select

Select list of items from table:

  • table(name).select(): get all records of table name
  • table(name).select(Integer maxRecords): get max maxRecords records of table name
  • table(name).select(String[] fields): get records of table name with only the specified fields
  • table(name).select(String view): get records of table name with the specified view (more about views)
  • table(name).select(Sort sortation): get records of table name using sort to sort records (More about Sort here)
  • table(name).select(Query query): get records of table name using query to filter

Example

Base base = new Airtable().base("AIRTABLE_BASE");
List<Movie> retval = base.table("Movies", Movie.class).select();

Detailed example see TableSelectTest.java

API Result Limitation

The REST-API of Airtable is limited to return max. 100 records. If the select has more than 100 records in result an offest is added to returned data. The Airtable.java client will solve this and tries to load the offset data automatically.

Find

Use find to get specific records of table:

  • table(name).find(String id): get record with id of table name

Example

Base base = new Airtable().base("AIRTABLE_BASE");
Table<Actor> actorTable = base.table("Actors", Actor.class);
Actor actor = actorTable.find("rec514228ed76ced1");

Detailed example see TableFindTest.java

Destroy

Use destroy to delete a specific records of table:

  • table(name).destroy(String id): delete record with id of table name

Example

Base base = airtable.base("AIRTABLE_BASE");
Table<Actor> actorTable = base.table("Actors", Actor.class);
actorTable.destroy("recapJ3Js8AEwt0Bf");   

Detailed example see TableDestroyTest.java

Create

First build your record. Then use create to generate a specific records of table:

  • Table<Actor> actorTable = base.table("Actors", Actor.class); Actor newActor = new Actor(); newActor.setName("Neuer Actor");: build your record

    Actor test = actorTable.create(newActor);: create the recently build record

Example

// detailed Example see TableCreateTest.java
Base base = airtable.base("AIRTABLE_BASE");
        
Table<Actor> actorTable = base.table("Actors", Actor.class);
Actor newActor = new Actor();
newActor.setName("Neuer Actor");
Actor test = actorTable.create(newActor);

Detailed example see TableCreateRecordTest.java

Update

Use update to update a record of table:

  • Actor.setName("New Name");: set or update to a new Value

    Actor test = actorTable.update(Actor);: update the Actor in the Table

Example

// detailed Example see TableCreateTest.java

Actor marlonBrando = ...;

marlonBrando.setName("Marlon Brando");
Actor updated = actorTable.update(marlonBrando);

Detailed example see TableUpdateTest

Roadmap

Short overview of features, which are supported:

  • Airtable Configure

    • configuration of proxy
    • configure user/password for proxy
    • configuration of AIRTABLE_API_KEY & AIRTABLE_BASE
    • configuration of requestTimeout
  • Select Records

    • SelectAll
    • Queries (maxRecords, sort & view )
    • Support of filterByFormula
    • Support of paging
    • Support of appending offset data
  • Find Record

  • Create Record

  • Update Record

  • Replace Record (could be done by update)

  • Delete/Destroy Record

  • General requirements

    • Automatic ObjectMapping
      • Read: convert to Objects
      • Read: conversion of Attachments & Thumbnails
      • Write: convert Objects to JSON
  • Errorhandling

Contribute

see: CONTRIBUTING.md

Testing

There are JUnit tests and integration tests to verify the API.

For unit testing, the JSON-responses are mocked by WireMock.

The integration tests are based on the Airtable template Movies, which could be created in your own account to run integration tests. Add your configuration of AIRTABLE_API_KEY & AIRTABLE_BASE to the integration tests locally.

Other Airtable Projects

Credits

Thank you very much for these great frameworks and libraries provided open source!

We use following libraries:

License

MIT License, see LICENSE

airtable.java's People

Contributors

codacy-badger avatar dependabot[bot] avatar fstuff avatar joesondow avatar stritti avatar vcmboot avatar zelle97 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

airtable.java's Issues

Unexpected NOT FOUND error when select()ing a table with a accented name

Hello Airtable team,
Just stumbled upon a weird error while trying to select rows from a table that has an accented name. (éèà...)

when I do a base.getTable("Accentué").select() it throws a NOT FOUND error. I first suspected that the name should be URLEncoded, which I did: getTable(URLEncoder.encode("Accentué", StandardCharsets.UTF_8)).select() but it hit me with the same error. Can't figure out why. Also, when I do a curl (with and without url encode), it works as expected.

Do you have any ideas ?

Spurious "Invalid cookie header" warnings

This spurious warning shows up in my logs every time I execute a remote call from my local machine or from AWS Lambda (in GMT) to Airtable. It happens on both reads and writes. I'm just using the airtable.java library with no customizations of the cookie headers.

WARNING: Invalid cookie header: "Set-Cookie: brw=bfwPbO3TrDZZa5sPw; path=/; expires=Fri, 20 Mar 2020 03:42:39 GMT; domain=.airtable.com; secure; httponly". Invalid 'expires' attribute: Fri, 20 Mar 2020 03:42:39 GMT

Release in Maven

Hello

Could you deploy 0.2.2 version in maven repository

Thank you

Support for abstract class inheritance

Currently the SDK doesn't support for Abstract field inheritance.
UserInfo is defined as follow: (written in Kotlin)

abstract class UserInfo(
        @SerializedName("First Name")
        @NotBlank
        open var firstName: String? = null,

        @SerializedName("Last Name")
        @NotBlank
        open var lastName: String? = null ) {}

and I have Student class which inherit from UserInfo as follow

class Student constructor() : UserInfo() {

    @SerializedName("Student CMKL ID")
    var studentId: String? = null
// ... more fields
)

but when I do select() the firstName and lastName aren't mapped out.

Table warns about using @SerializedName even if you already are using it

Table does not really use any logic when deciding whether or not to throw a warning re. the need to use the SerializedName annotation.
Excerpt from Table.java:

  if (key.contains(" ") || key.contains("-")) {
            LOG.warn("Annotate columns having special characters by using @SerializedName for property: [" + key + "]");

The result is that every time there is a select operation this warning is generated. It cruds up logs and is therefore annoying. However, it appears not to break anything.

The solution would be to check from the presence of the SerializedName annotation, and only throw the warning if it is not present.

Android HTTP AllowAllHostnameVerifier Error

Hey, I'm running into this HTTP error when I attempt to initialize and configure the Airtable object. Seems like it's common problem from my search online but I'm not familiar with HTTP so I'm still not sure how to resolve this issue. I'm running the app on an Pixel 3 API 29 emulator using Android Studio 3.5.1. I'm using airtable.java version 0.2.0. Is my project somehow using the wrong Apache HTTP library?

Updated: I see that there's an android port here https://github.com/Sybit-Education/airtable.android but I don't know how to apply it. Could provide some instructions or point me to an article please?

Here is my code (inside onCreate of MainActivity):

    // Initialize Airtable
    try {
        Airtable airtable = new Airtable();
        airtable.configure(AIRTABLE_API_KEY); // Runtime crash happens in this call
    } catch (AirtableException e) {
        e.printStackTrace();
    }

And this is the error I get:
E/AndroidRuntime: FATAL EXCEPTION: main Process: saeed.org.recipeat, PID: 15322 java.lang.NoSuchFieldError: No static field INSTANCE of type Lorg/apache/http/conn/ssl/AllowAllHostnameVerifier; in class Lorg/apache/http/conn/ssl/AllowAllHostnameVerifier; or its superclasses (declaration of 'org.apache.http.conn.ssl.AllowAllHostnameVerifier' appears in /system/framework/framework.jar!classes3.dex) at org.apache.http.conn.ssl.SSLConnectionSocketFactory.<clinit>(SSLConnectionSocketFactory.java:146) at org.apache.http.conn.ssl.SSLConnectionSocketFactory.getSocketFactory(SSLConnectionSocketFactory.java:174) at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.getDefaultRegistry(PoolingHttpClientConnectionManager.java:115) at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.<init>(PoolingHttpClientConnectionManager.java:122) at com.mashape.unirest.http.options.Options.refresh(Options.java:72) at com.mashape.unirest.http.options.Options.<clinit>(Options.java:46) at com.mashape.unirest.http.options.Options.setOption(Options.java:35) at com.mashape.unirest.http.Unirest.setProxy(Unirest.java:65) at com.sybit.airtable.Airtable.setProxy(Airtable.java:185) at com.sybit.airtable.Airtable.configureProxy(Airtable.java:213) at com.sybit.airtable.Airtable.configure(Airtable.java:155) at com.sybit.airtable.Airtable.configure(Airtable.java:113) at com.sybit.airtable.Airtable.configure(Airtable.java:100) at saeed.org.recipeat.MainActivity.onCreate(MainActivity.java:45) at android.app.Activity.performCreate(Activity.java:7802) at android.app.Activity.performCreate(Activity.java:7791) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1299) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409) at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83) at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016) at android.os.Handler.dispatchMessage(Handler.java:107) at android.os.Looper.loop(Looper.java:214) at android.app.ActivityThread.main(ActivityThread.java:7356) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)

Error when trying to update

I am getting this error "Field "People ID" cannot accept a value because the field is computed (INVALID_VALUE_FOR_COLUMN)" and "Field "Talent's Name" cannot accept a value because the field is computed (INVALID_VALUE_FOR_COLUMN)", when I try to update a record. The only field I update is a field called "Status" and nothing else, but for some reason the API tried to update every column that the table has. Basically it tries to update lookup fields even though I don't want it to change them. Can you please help me?

image
image

Examples

Hi, just wondering where i can find examples for this API? The links in your README don't work.

Could you let me where I could find some?

EDIT: Specifically I'm looking for examples on getting records of table name with the specified view. I keep getting endpoint url null pointer exceptions.

Thanks!

JCenter Shutdown

Move Artifacts

  • As JCenter is being shutdown in 2022, this api will need to be moved soon. Maven central would be appreciated.

Getting record id from table

@stritti I think i have found a bug.

Trying to print all record id's from a formula field in airtable. The formula is using the RECORD_ID() function to display all the ID's.

String[] field= {"Record_ID"};


        System.out.println(table.select(field).size());
        List<User> recordIDs = table.select(field);

        for (User user : recordIDs) {
            System.out.println(user.getRecordID().toString());
          }

It returns null for each value but it .size() shows all values are there.

Any help would be much appreciated!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.