Coder Social home page Coder Social logo

facebook-java-business-sdk's Introduction

Facebook Business SDK for Java

BREAKING CHANGES NOTES (v3.0.0): New Release for the Java SDK (v3.0.0) includes following breaking changes:

  • API version upgrade: The new SDK version calls Facebook Graph API endpoints related to the Pages, Instagram, Business Manager, and Marketing products. Classes now use new fields/params/endpoints. Please refer to the Graph API Changelog for details.

Introduction

The Facebook Business SDK is a one-stop shop to help our partners better serve their businesses. Partners are using multiple Facebook API's to server the needs of their clients. Adopting all these API's and keeping them up to date across the various platforms can be time consuming and ultimately prohibitive. For this reason Facebook has developed the Business SDK bundling many of its APIs into one SDK to ease implementation and upkeep. The Business SDK is an upgraded version of the Marketing API SDK that includes the Marketing API as well as many Facebook APIs from different platforms such as Pages, Business Manager, Instagram, etc.

facebook-java-business-sdk is a Java library that provides an interface between your Java application and Facebook's Graph API. This tutorial covers the basics, including examples, needed to use the SDK.

Quick Start

Business SDK Getting Started Guide

Pre-requisites

Register An App

To get started with the SDK, you must have an app registered on developers.facebook.com.

To manage the Marketing API, please visit your App Dashboard and add the Marketing API product to your app.

IMPORTANT: For security, it is recommended that you turn on 'App Secret Proof for Server API calls' in your app's Settings->Advanced page.

Obtain An Access Token

When someone connects with an app using Facebook Login and approves the request for permissions, the app obtains an access token that provides temporary, secure access to Facebook APIs.

An access token is an opaque string that identifies a User, app, or Page.

For example, to access the Marketing API, you need to generate a User access token for your app and ask for the ads_management permission; to access Pages API, you need to generate a Page access token for your app and ask for the manage_page permission.

Refer to our Access Token Guide to learn more.

For now, we can use the Graph Explorer to get an access token.

Install package

To start using Java SDK, follow the instructions on Getting started instruction.

If you want to use pre-compiled .jar file, visit https://repo1.maven.org/maven2/com/facebook/business/sdk/facebook-java-business-sdk/ to download specific version. If you download the one without dependencies, you will need to download all dependent .jar files and add them to your path when build and run. Use the .pom file in the version directory to decide dependencies.

Run Sample code

Here is the minimal code needed to create a campaign in your ad account. If your app and build environments are set up correctly, this code should compile and run without error. You can verify the created campaign in Ads Manager.

import com.facebook.ads.sdk.APIContext;
import com.facebook.ads.sdk.AdAccount;
import com.facebook.ads.sdk.AdAccount.EnumCampaignStatus;
import com.facebook.ads.sdk.AdAccount.EnumCampaignObjective;
import com.facebook.ads.sdk.Campaign;
import com.facebook.ads.sdk.APIException;

public class QuickStartExample {

  public static final String ACCESS_TOKEN = "[Your access token]";
  public static final Long ACCOUNT_ID = [Your account ID];
  public static final String APP_SECRET = "[Your app secret]";

  public static final APIContext context = new APIContext(ACCESS_TOKEN, APP_SECRET);
  public static void main(String[] args) {
    try {
      AdAccount account = new AdAccount(ACCOUNT_ID, context);
      Campaign campaign = account.createCampaign()
        .setName("Java SDK Test Campaign")
        .setObjective(Campaign.EnumObjective.VALUE_LINK_CLICKS)
        .setSpendCap(10000L)
        .setStatus(Campaign.EnumStatus.VALUE_PAUSED)
        .execute();
      System.out.println(campaign.fetch());
    } catch (APIException e) {
      e.printStackTrace();
    }
  }
}

More examples can be found in the /examples folder.

Understanding the Business SDK

Please see the Business SDK Documentation for more information about implementation and common scenarios. The Business SDK is consistent with v3.0 endpoints related to Pages, Business Manager, Instagram and Marketing products. Please refer to APIs within the Business SDK to get the list of APIs that are within the Business SDK.

Get an object

You always need to create an APIContext before making any API calls. APIContext includes your access token and app secret:

APIContext context = new APIContext(ACCESS_TOKEN, APP_SECRET);

To fetch a campaign object:

Campaign campaign = new Campaign(CAMPAIGN_ID, context); // this only creates a new empty object
campaign = campaign.get().requestAllFields().execute();
// 1. get() is the API call name to get the object;
// 2. requestAllFields() means you want all the fields. If you only want certain fields, then you can call requestXXXFields() instead, and sever response will only contain specified fields.
// 3. ***IMPORTANT*** any API calls should end with execute(), otherwise it will not be executed.

Or, you can use an equivalent shortcut:

Campaign campaign = Campaign.fetchById(CAMPAIGN_ID, context);

After fetching the object, you can read the data inside:

String id = campaign.getFieldId();
String name = campaign.getFieldName();
// Note that the methods to read field data are getFieldXXX(). This is to distinguish method names of field data from method names of API GET calls.

Update and Delete

Update:

campaign.update()
        .setName("Updated Java SDK Test Campaign") // set parameter for the API call
        .execute();

Delete:

campaign.delete().execute();

Edge Read and Write (Create Object)

Edge is a relational concept in Graph API.

For example, if you want to know all the campaigns under an ad account, then you call GET on the campaigns edge from the ad account object.

Or, if you want to create a new campaign under this account, then you call POST (create) on the campaigns edge of ad account.

Read:

AdAccount account = new AdAccount(ACCOUNT_ID, context);
APINodeList<Campaign> campaigns = account.getCampaigns().requestAllFields().execute();
for(Campaign campaign : campaigns) {
	System.out.println(campaign.getFieldName());
}

** Important **: Handling pagination: Most edge APIs have default pagination, which returns a limited number of objects (~30 objects) instead of the entire list. If you want to load more, you need to make a separate API call. In our SDK, you can call to nextPage():

campaigns = campaigns.nextPage();
  • Or, enable auto pagination iterator with:
campaigns = campaigns.withAutoPaginationIterator(true);

In this case, campaigns.iterator() will return an iterator that can fetch the next page automatically.

// Enhanced for loop
for(Campaign campaign : campaigns) {
	System.out.println(campaign.getFieldName());
}

// Foreach with lambda is also supported
campaigns.forEach(campaign -> System.out.println(campaign.getFieldName()));

// Note: APIException will be wrapped in a Runtime exception

To fetch all campaigns in your account.

With auto pagination iterator, next page will be fetched automatically in enhanced for loop and foreach loop. In this scenario, campaign.size(), campaign.get(i) is no longer reliable and shouldn't be used

Write (create object):

Most objects are under ad account. So you may always want to try account.createXXX() to create an object.

AdAccount account = new AdAccount(ACCOUNT_ID, context);
Campaign campaign = account.createCampaign()
        .setName("Java SDK Test Campaign")
        .setObjective(Campaign.EnumObjective.VALUE_LINK_CLICKS)
        .setSpendCap(10000L)
        .setStatus(Campaign.EnumStatus.VALUE_PAUSED)
        .execute();
// The create call only returns id of the new object.
// So you want to fetch() to get all the data of the object.
// fetch() is just another shortcut for
// campaign = campaign.get().requestAllFields().execute();
campaign.fetch();

Batch Mode

Every execute() is an HTTP request, which takes a network round trip. Facebook API does support batch mode, which allows you to make multiple API calls in a single HTTP request.

In this SDK, you can simply replace execute() with addToBatch() to prepare a batch API call. When it's ready, you call batch.execute().

Example:

      BatchRequest batch = new BatchRequest(context);
      account.createCampaign()
        .setName("Java SDK Batch Test Campaign")
        .setObjective(Campaign.EnumObjective.VALUE_LINK_CLICKS)
        .setSpendCap(10000L)
        .setStatus(Campaign.EnumStatus.VALUE_PAUSED)
        .addToBatch(batch, "campaignRequest");
      account.createAdSet()
        .setName("Java SDK Batch Test AdSet")
        .setCampaignId("{result=campaignRequest:$.id}")
        .setStatus(AdSet.EnumStatus.VALUE_PAUSED)
        .setBillingEvent(AdSet.EnumBillingEvent.VALUE_IMPRESSIONS)
        .setDailyBudget(1000L)
        .setBidAmount(100L)
        .setOptimizationGoal(AdSet.EnumOptimizationGoal.VALUE_IMPRESSIONS)
        .setTargeting(targeting)
        .addToBatch(batch, "adsetRequest");
      account.createAdImage()
        .addUploadFile("file", imageFile)
        .addToBatch(batch, "imageRequest");
      account.createAdCreative()
        .setTitle("Java SDK Batch Test Creative")
        .setBody("Java SDK Batch Test Creative")
        .setImageHash("{result=imageRequest:$.images.*.hash}")
        .setLinkUrl("www.facebook.com")
        .setObjectUrl("www.facebook.com")
        .addToBatch(batch, "creativeRequest");
      account.createAd()
        .setName("Java SDK Batch Test ad")
        .setAdsetId("{result=adsetRequest:$.id}")
        .setCreative("{creative_id:{result=creativeRequest:$.id}}")
        .setStatus("PAUSED")
        .setBidAmount(100L)
        .addToBatch(batch);
      List<APIResponse> responses = batch.execute();
      // responses contains the result of each API call in order. However, if the API calls have dependency, then some result could be null.

Error Handling

Currently all the errors are wrapped in APIException and its subclasses.

MalformedResponseException is caused by the improper parsing of a server response (likely a bug in the SDK).

FailedRequestException is caused by either a client error or server failure. See details in the next section.

We have a plan to improve this by adding more details and providing a convenient function to get the error code.

Customization and Debugging

Enable debugging

You can enable the debug output by setting the APIContext to debug mode:

public static final APIContext context = new APIContext(ACCESS_TOKEN, APP_SECRET).enableDebug(true).setLogger(System.out);

This will print out the network requests and responses. By default it prints on STDOUT, but you can customize by calling .setLogger(PrintSteam)

Customize Network

In v0.2.0, we added APIRequest.changeRequestExecutor(IRequestExecutor), which can be used to set your own network request executor. This makes it possible to add proxy settings, automatic retry, or better network traffic management. See /example/NetworkCustomizationExample.java.

Currently this is a static method because it is likely to be a global setting. If you do think object-level Customization is needed, we'll add that functionality.

The executor needs to implement IRequestExecutor interface:

    public static interface IRequestExecutor {
        public String execute(String method, String apiUrl, Map<String, Object> allParams, APIContext context) throws APIException, IOException;
        public String sendGet(String apiUrl, Map<String, Object> allParams, APIContext context) throws APIException, IOException;
        public String sendPost(String apiUrl, Map<String, Object> allParams, APIContext context) throws APIException, IOException;
        public String sendDelete(String apiUrl, Map<String, Object> allParams, APIContext context) throws APIException, IOException;
    }

DefaultRequestExecutor is used by default, and it is also a good starting point for Customization.

Missing or Incorrect Request Params/Fields

It is recommended to use setXXX() or requestXXXField() to construct a proper APIRequest, which prevents mis-spelling of parameter/field names. However, if you believe that some needed params/fields are missing from these methods, you can call:

    APIRequest.setParam(param, value)
    APIRequest.setParam.requestField(field, true)

This also works if you believe the type of the param is not correct in SDK.

In this case, please help us make improvement by filing issues.

Missing Fields in Class Definition

If you believe that certain fields are returned from server, but they are missing in class definition, then you can still access those fields by fetching it from raw response:

campaign.getRawResponseAsJsonObject().get("field").getAsString();

This situation can occasionally happen if new fields are added to server response while SDK is not up-to-date. We'll update the SDK periodically to include new fields.

Ad-hoc APIRequest

Most of Marketing API can be found in SDK classes. If you don't find the one you want to access, it is possible to construct an Ad-hoc APIRequest:

    APIRequest<AdAccount> request = new APIRequest<AdAccount>(context, "me", "/adaccounts", "GET", AdAccount.getParser());
    APINodeList<AdAccount> accounts = (APINodeList<AdAccount>)(request.execute());

When constructing the APIRequest, you need to provide

  • APIContext, which has the access token,
  • The node ID, which is typically a long number, but it can also be some alias, like "me",
  • The edge name, which should start with "/"; if it's for a Node API, then use "/"
  • The HTTP Method, GET/POST/DELETE
  • The parser for the expected response type. You can use null if it is not in the SDK, which will return APINodeList when executed.

FailedRequestException Troubleshooting

There are many possible causes for a failed request:

  • Incorrect parameters are provided in the API request (check Graph API Docs)
  • Permission issue (check your access token or app secret)
  • SDK bug (report on Github)
  • Temporary network issue (check your network and retry)
  • Temporary server issue (retry, or report on Facebook Platform Bugs if it happens too often)
  • Server bug (report on Facebook Platform Bugs)

As the first step of troubleshooting, please enable debugging in the APIContext.

Here are some hints on troubleshooting:

  • If it's caused by incorrect parameters, you'll see error descriptions in the exception message.
  • If it's caused by permission issue, you'll see error message like "permission denied" or "unknown path"
  • If in stack trace you see that the failed request is caused by exceptions such as NullPointerException or MalformedResponseException, it is likely a SDK bug (or your own bug, depending on the stacktrace).
  • If you see in the debug message that the params sent to server don't match what you specified, it is possible that you didn't specify the param correctly, or SDK didn't assemble the request properly.
  • For temporary server issue, typically retry should work after a few seconds.
  • If server persistently responds with "Unknown error," then it is potentially server bug.

SDK Codegen

Our SDK is autogenerated from SDK Codegen. If you want to learn more about how our SDK code is generated, please check this repository.

License

Facebook Business SDK for Java is licensed under the LICENSE file in the root directory of this source tree.

facebook-java-business-sdk's People

Contributors

bryant1410 avatar cloudxu avatar daphyfb avatar dependabot[bot] avatar donglinw-fb avatar eray-aydin avatar heymultiverse avatar hindol avatar igustafson avatar jiamingfb avatar jingping2015 avatar joesus avatar kilink avatar kongxinzhu avatar linmx0130 avatar marksliva avatar mxiim avatar shootingsyh avatar stcheng avatar uwemaurer avatar vicdus avatar windsfantasy6 avatar xardazz avatar xiaotchen 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  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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 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  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

facebook-java-business-sdk's Issues

Use slf4j for logging

The package currently uses a PrintStream instance for logging. IMO it would be better to use slf4j, which gives consumers control over which logging framework is used, how logging is done, finer grained control over which kinds of messages are logged, etc.

AdCreativeLinkDataCallToActionValue is not utilized

When creating an AdCreative, passing an instance of AdCreativeLinkDataCallToActionValue to adCreativeLinkDataCallToAction.setFieldValue(..) doesn't have an effect - those CTA parameters are not present in the resulting adCreative.

Instead, we are forced to use the form adCreativeLinkDataCallToAction.setFieldValue(String s), and pass in json in a string - only then do we see the correct CTA parameters on the resulting adCreative.

Sample Code Not Working

Sample code to create a campaign listed on the main Code page on Github, doesn't work. Sample code within the Examples folder for QuickStartExample, doesn't work.

Does anyone have any working sample code to get this working?

Fetching businesses leads to NPE

Business.java, row 149, inside parseResponse():

JsonObject paging = obj.get("paging").getAsJsonObject().get("cursors").getAsJsonObject();

This causes a null pointer exception in API when trying to fetch all businesses of a user like this:

APINodeList<Business> x = (APINodeList) ((APINodeList) (new APIRequest(context, "", "/me/businesses", "GET", Business.getParser())).execute());

Reason is that the API endpoint in question doesn't return cursors.

Add optional retry for transient errors.

I get a decent amount of transient errors while calling the Facebook api. Immediate retries of the same request work. It would be nice to add retry support into the sdk, possibly in APIRequest.callInternal(). The response has the is_transient field in it, if this is true it would be nice if the sdks retried instead of all calling clients to have to catch the APIException, check if it it is transient and then retry everywhere a request is made. Making this optional by adding a boolean (retry) with the number of retry attempts to the APIContext would allow for users to turn retries on or off.

Exception from sdks:
com.facebook.ads.sdk.APIException: {"error":{"message":"An unexpected error has occurred. Please retry your request later.","type":"OAuthException","is_transient":true,"code":2,"fbtrace_id":"DAbvR5wiN2d"}}

Proxy Settings in SDK API

Is there any option to setup proxy settings in sdk/api, because most of organization have proxy server for Internet access. Thanks

Put user limitation

Hi

i try to put 'madid'( Android advertising ID) to custom audience.

and i want to know limitation of user's data.

if i had tried to put 30000 data,
i got {"error":{"code":1,"message":"An unknown error occurred","error_subcode":99}}

so could you let me know limitation of added user.

Retrieve Saved Audience

I can retrieve customaudiences from ad_account
/act_{ad_account_id}/customaudiences

But it doesn't include saved audience (the one contain geolocation, gender, interest, locale).
Pls advise how to retrieve this data

screen shot 2016-11-04 at 11 02 12 am

Ajax error is not formatted correctly

Currently, ajax error message is:

responseText: "{"success":false, "code": 13, "message": "{"error":{"message":"Invalid parameter","type":"OAuthException","code":100,"error_data":{"blame_field_specs":[["daily_budget"]]},"error_subcode":1885272,"is_transient":false,"error_user_title":"Your Budget Is Too Low","error_user_msg":"The minimum budget for this ad set is $19.90.","fbtrace_id":"B8zThZN6jAv"}}"}"

Which cannot parse by JSON.
The correct one should be: (removing the double quote around responseText.message

{"success":false, "code": 13, "message": {"error":{"message":"Invalid parameter","type":"OAuthException","code":100,"error_data":{"blame_field_specs":[["daily_budget"]]},"error_subcode":1885272,"is_transient":false,"error_user_title":"Your Budget Is Too Low","error_user_msg":"The minimum budget for this ad set is $19.90.","fbtrace_id":"B8zThZN6jAv"}}}

Reasons for supporting EnumOptimizationGoal 'Clicks' in AdSet

Hi there

Why do you support OptimizationGoal 'Clicks' in AdSet (EnumOptimizationGoal)? This feature isn't supported by the facebook api since version 2.4.

@SerializedName("CLICKS")
VALUE_CLICKS("CLICKS")

If it's a failure, I will create a PR.

Thanks in advance.

Kind regards, Patrick

Cannot get tabs from user/account

Hi,
In the previous version, I could get pages' tabs from ConnectionObject node.
In 2.6, I couldn't get this object from account (page) node, as it throws exception:
" Requires either an app access token, or a page access token for this Page"

Is that intended feature? I'm able to get promotable_posts from this node, so just want to double check.
Thanks.

    User user = new User(fbUserId, context);        

    APINodeList<APINode> accountList = user.getAccounts()

                            .requestField("id")

                            .requestField("name")

                            .requestField("promotable_posts")

                            //.requestField("tabs") //require page accesstoken

                            .requestField("picture").execute();

java 1.7 support?

Hi, it seems like current package only supports java 1.8+, while some of our exists projects are using 1.7 or older. It requires a lot of extra works to upgrade all our projects to java 1.8. Would you plan to support java1.7 in the future?

Stream-based video upload API

It would be nice if VideoUtils exposed a stream-based API for uploading videos, as opposed to only offering a File based one as it does now. This can be achieved with a minor refactoring of the existing code, where the File-based methods delegate to a stream-based one.

Move IRequestExecutor to APIContext

APIRequest delegates to IRequestExecutor to make all HTTP calls; currently a default implementation is used and stored in a static field in APIRequest, with static methods which can be used to override it.

This makes it awkward for testing, as you then have global state you need to setup and teardown, which also precludes parallelizing test runs. It also makes it impossible to use different IRequestExecutors for different kinds of requests without synchronization or some sort of coordination (admittedly I don't have a use case for this).

Wouldn't it make more sense for the IRequestExecutor configuration to live somewhere else, for example APIContext?

Avoiding "User request limit reached"

I haven't ran a wireshark (too lazy), but I seem to be running into the issue with 200 requests per hour max over an account with only 25 ads.

I have code that looks like this:
APINodeList ads = adAccount.getAds()..[blah blah blah]..execute() (1 call, returns 25 ads)
Then I go through all ads, requesting insights:
for (Ad ad : ads) {
APINodeList adInsights = ad.getInsights().[blah].execute() (should get called 25 times)
methodThatExaminesInsights(each adInsight)
}

Now considering there should be only 26 calls to go to backend, I getthe 200-max error after going through 180 or so insights. Which means that looking at an insight generates a call?

This seems silly as that means there is no way to examine even a single account's insights

Seems like a bug.

Any help would be appreciated.

How to get audience_size of specific audience name ?

I have a set of audiences name, but not audience id.
How can I get the size of each audience, audience type and audience id.
Example: I have exactly name of audience: "Design Engineer". I want to get audience type is "work_positions", audience id is "109542932398298" and audience size is "105197"

Thanks !

autocomplete search

Hi,
Does the SDK support autocomplete search for targeting objects such as (location, locale..)
I was trying to use APIRequestGetTargetingSearch class, but couldn't execute on AdAccount Node.

Basically I'm trying to build query like this: search?q=un&type=adgeolocation
Please let me know if I misunderstanding about this functionality.
Thanks,

how to get pagination for adhoc request

Hi team,
Just have a question, how does pagination work for cases like below:

    APIResponse res = new APIRequest<APINode>(context, "", "search", "GET").execute(params);

Please advise.
Thanks,
Sang

Duplicate AdSets

Is there any way to quickly duplicate the adsets with its ads and ad creative?

Documentation for detailed targeting.

I was unable to find enums or documentation on targeting adverts on Facebook.
For eg: "setFieldGenders( )" takes a list of long as an arguments but its not clear which number corresponds to which gender, can you point me to a documentation which I can refer for these cases?

Thanks in advance.
Pushkar

NullPointerException throws while trying to access /me/businesses

Hi ,

I'm using java sdk v0.4. It seems like there has no method to allow me to list all businesses belongs to the user. So I just use the following code as alternative:
APIRequest<Business> request = new APIRequest<Business>(context, "me", "/businesses", "GET",Business.getParser());
The API response correctly as expect:
{"data":[{"name":"Alibaba advertising","id":"7349984ACCOUNTID72"}],"paging":{"next":"https://graph.facebook.com/v2.8/130101310692072/businesses?access_token=MY_ACCESS_TOKEN&limit=25&offset=25&__after_id=enc_AdCRaZCZAD9ZAbIQDB7lYwCoNqAaNcqRbEWaRPZCHaPS8eSxQ11pUw7nHnOC1ZCBGm6moP4vaYSOp3D132M032XHZBUG3P"}}

But this line of code throws a NullPointerException which I think it shouldn't:
JsonObject paging = obj.get("paging").getAsJsonObject().get("cursors").getAsJsonObject();
The above code can be found at Business.java, line 163.

Would you be kindly to take a look? Thanks a lot.
-Peng

How to get Ads using facebook java SDK

can you help me to get the ads of a campaign using the facebook java API.

and can u also provide a proper documentation for the facebook-java-ads-sdk.

Use a single Gson instance

It looks like all of the objects in com.facebook.ads.sdk.* have the same static, synchronized method for constructing the Gson object:

synchronized /*package*/ static Gson getGson() {
    if (gson != null) {
      return gson;
    } else {
      gson = new GsonBuilder()
        .excludeFieldsWithModifiers(Modifier.STATIC)
        .excludeFieldsWithModifiers(Modifier.PROTECTED)
        .disableHtmlEscaping()
        .create();
    }
    return gson;
}

Gson instances are threadsafe, and therefore a single instance could be shared throughout the codebase. Maybe the APIContext can grow a method for getting the Gson instance? It would also make it easier for consumers to override the defaults.

The library depends on gson version 2.5:

You should consider testing it with more versions - maybe 2 versions (so apps that use a different version of gson). For us it's not an issue.
Your pom should specify which versions are acceptable.
e.g.:
[2.4,2.5]

This is low priority from our end (since it does not collides) but might be an issue for an app that is using gson on different version then 2.5

Uploading video caption file fails

Uploading of video captions fails due to the way the default request executor determines mime types based on file extension; it uses a fixed mapping that doesn't include ".srt", so the Facebook API endpoint rejects the request.

A more foolproof method would be to fall back to a default mimetype such as "application/octet-stream" when one can't be determined based on file extension. Files.probeContentType could also be utilized to delegate to more sophisticated user supplied file type detectors such as Tika.

Uploading Custom Audience

There is no guide or example for creating & using custom audience. Uploading Custom audience of phone number, email, Mobile advertising ID etc.

URL tags creating error (V2.6)

Hi,
I'm still using v2.6 and I got this error while creating ad with url_tags having more than 1 value:

creative to submit:
{"body":"test desc","image_hash":"c6e035cb89c48000b7e5eb8af0e2b012","link_url":"http://sdinh.net","object_url":"http://sdinh.net","title":"my headline","url_tags":"key=1&key=2"}

error:
{\"message\":\"(#100) Creative spec must be an associative array (optionally json-encoded)

It happened with different type of creative (Domain, Post page ad...).
Can you take a look and advise.

Thanks,
Sang

Should we also support async API?

Hi, I think that a lot of Java/Scala developers would love to use this project. So should we support them with an Async API? For example, we can use Retrofit to support Observable API calls (this is just an example, we don't have to use it).

The main point is this project will mostly be used by some backend projects. And with them I think that providing some Observable or CompletableFuture APIs is really a need.

I can also help to develop some code. :)

AdsInsights's bug

0.4.0 AdsInsights can not get all breakdown data "age","country","gender","impression_device" and other.

error create Link Ad Preview

Hi,

I'm not sure it's right place to post this question, it seems happening to python SDK as well.
For me I'm using this java-sdk to develop my app. So I just want to post here, in case any one can take a look and advise.

I'm trying to get ad-preview for a link ad based on
https://developers.facebook.com/docs/marketing-api/reference/ad-creative-link-data/

"The preview iframe received doesn't render creative but showing:
Using unsupported field in object_story_spec: The field force_single_link is not supported in the field link_data of object_story_spec."

Can you advise what need to be done for this field: force_single_link?
I've tried different cases: remove this field from object_story_spec, set true or false, but still having same error.


AdCreative creative = new AdCreative();
AdCreativeObjectStorySpec objStorySpec = new AdCreativeObjectStorySpec();
AdCreativeLinkData linkData = new AdCreativeLinkData();
linkData.setFieldLink(obj.getString("link_url"));
//linkData.setFieldForceSingleLink(false);
linkData.setFieldImageHash(obj.getString("image_hash"));

objStorySpec.setFieldLinkData(linkData);
objStorySpec.setFieldPageId(obj.getString("page_id"));
creative.setFieldObjectStorySpec(objStorySpec);

Thanks
Sang

SDK - support of API versions

Although it seems like it is designed for supporting multiple versions of the API I see few issues:

  1. Technical - the current APIContext Constructor that accepts a version is protected and only the default which is defined in the config is available (it's 2.5 for now).
  2. Conceptual - Versions has breaking changes. We have been writing internally an "SDK" (a bit less generic and holds only the API calls we are using) for a long time. The best way to do it is by providing a package name with the version main.java.....sdk.2-5. Once you have a new version you start with copying it and adding a new package ... skd-2.6 and then you update according to the breaking changes.
    This way a client of the library is really able to choose which versions to use, you can maintain one master branch supporting few versions in parallel and once a version is deprecated, you delete the package.

Hope this makes sense
@christinelu FYI

AdAccount.fetch() throws FailedRequestException

Hello,

My application receives FailedRequestException exception, when it tries to AdAccount.fetch()

Exception: com.facebook.ads.sdk.APIException$FailedRequestException: {"error":{"message":"(#100) Tried accessing nonexisting field (last_used_time) on node type (AdAccount)","type":"OAuthException","code":100,"fbtrace_id":"GHeibz8E4TY"}}
at com.facebook.ads.sdk.APIRequest.readResponse(APIRequest.java:223)
at com.facebook.ads.sdk.APIRequest.access$100(APIRequest.java:44)
at com.facebook.ads.sdk.APIRequest$DefaultRequestExecutor.sendGet(APIRequest.java:344)
at com.facebook.ads.sdk.APIRequest$DefaultRequestExecutor.execute(APIRequest.java:322)
at com.facebook.ads.sdk.APIRequest.executeInternal(APIRequest.java:157)
at com.facebook.ads.sdk.AdAccount$APIRequestGet.execute(AdAccount.java:12225)
at com.facebook.ads.sdk.AdAccount$APIRequestGet.execute(AdAccount.java:12220)
at com.facebook.ads.sdk.AdAccount.fetchById(AdAccount.java:187)
at com.facebook.ads.sdk.AdAccount.fetch(AdAccount.java:173)

It seems that facebook changed schema, and now they are not returning 'last_used_time' field
java SDK should be changed accordingly.

Thanks,

BatchRequest size limit

Hello,

Is there any chance that the 50 requests limit per batch could be increased ?

Thank you !
Kind Regards !
Catalin

Upload progress (v2.5)

When upload the video, we want to show upload progress bar, so how to get the progress percent from FaceBook?

Conversion tracking

Hi,

I'm trying to create an ad with all the Tracking settings in place. By all the tracking settings I mean pixel ID and URL parameters.

I tryed with something like this:

final ConversionActionQuery caq = new ConversionActionQuery();
        caq.setFieldFbPixel(Arrays.asList("621916377890091"));

        //formatter:off
        final Ad ad = account.createAd()
                        .setName("Java SDK Test ad")
                        .setAdsetId(Long.parseLong(adSet.getId()))
                        .setCreative(creative)
                        .setStatus("PAUSED")
                        .setBidAmount(100L)
                        .setRedownload(true)
                        .setTrackingSpecs(Arrays.asList(caq))
                        .execute();
        //formatter:on

but I get the StackOverflow exception

Caused by: java.lang.StackOverflowError: null
    at java.lang.Class.isPrimitive(Native Method) ~[na:1.8.0_65]
    at com.google.gson.internal.$Gson$Types.checkNotPrimitive($Gson$Types.java:432) ~[gson-2.3.1.jar:na]
    at com.google.gson.internal.$Gson$Types.access$000($Gson$Types.java:43) ~[gson-2.3.1.jar:na]
    at com.google.gson.internal.$Gson$Types$WildcardTypeImpl.<init>($Gson$Types.java:542) ~[gson-2.3.1.jar:na]
    at com.google.gson.internal.$Gson$Types.canonicalize($Gson$Types.java:109) ~[gson-2.3.1.jar:na]
    at com.google.gson.internal.$Gson$Types$WildcardTypeImpl.<init>($Gson$Types.java:551) ~[gson-2.3.1.jar:na]
    at com.google.gson.internal.$Gson$Types.canonicalize($Gson$Types.java:109) ~[gson-2.3.1.jar:na]
    at com.google.gson.internal.$Gson$Types$WildcardTypeImpl.<init>($Gson$Types.java:544) ~[gson-2.3.1.jar:na]
    at com.google.gson.internal.$Gson$Types.canonicalize($Gson$Types.java:109) ~[gson-2.3.1.jar:na]

Any tips on how to make it work with the current SDK?

Thanks!

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.