Last Updated: February 25, 2016
·
1.273K
· themichael'tips

AdWords API in Java without Client Library

Introduction

The tutorial Using the AdWords API in Java without the Client Library is outdated, here you can find tips to update and improve your client.

Tip 1: automate wsdl2java process

Once you have downloaded the wsdl file of your google service, add this code to your maven configuration file in order to extract and create the related java code of the service. This is done by wsdl2java binary.

<build>
 <!--  ..your stuff here.. -->
  <plugins>
    <plugin>
      <groupId>org.apache.cxf</groupId>
      <artifactId>cxf-codegen-plugin</artifactId>
      <version>${cxf.version}</version>
      <executions>
        <execution>
          <id>generate-sources</id>
          <phase>generate-sources</phase>
          <configuration>
            <wsdlOptions>
              <wsdlOption>
                <wsdl>src/main/resources/your_google_service.wsdl</wsdl>
              </wsdlOption>
            </wsdlOptions>
          </configuration>
          <goals>
            <goal>wsdl2java</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
  </plugins>
  <finalName>google</finalName>
</build>

Tip 2: OAuth client sucks

Looking at the OAuth google's client, you can find within the package com.google.api.ads.common.lib.auth a bad code like this:

public class OfflineCredentials {

  /**
   * Enum representing the API that OfflineCredentials can be used for.
   */
  public static enum Api {
    ADWORDS("api.adwords.", AdWordsInternals.getInstance()),
    DFA("api.dfa.", DfaInternals.getInstance()),
    DFP("api.dfp.", DfpInternals.getInstance());

    private final String propKeyPrefix;
    private final Internals internals;

    private Api(String propKeyPrefix, Internals internals) {
      this.propKeyPrefix = propKeyPrefix;
      this.internals = internals;
    }

Expose internal class is an architectural error!

How define different services ? How can we extend one of the internal class to add/change some behaviour ? No way! You need to recompile the source code...etc...etc...

If you need to use different Google's api, not exclusively AdWords, for the authentication process you can cheat, and use one of the bellow services even if you don't directly use them.
A simple way to do authentication is:


import com.google.api.ads.common.lib.auth.OfflineCredentials;
import com.google.api.client.auth.oauth2.Credential;

Credential oAuth2Credential = new OfflineCredentials.Builder()
                .forApi(OfflineCredentials.Api.DFP)
                .fromFile()
                .build()
                .generateCredential();

Within your src/main/resources/ads.properties file you have to use the "api.dfp" prefix naming for your credentials.

Tip 3: HTTP Header

Customize the HTTP header in order to pass the "Authorization: Bearer ACCESS_TOKEN":

Map<String, List<String>> extraHeader = new HashMap<String, List<String>>();
extraHeader.put("Authorization", Arrays.asList("Bearer " + ACCESS_TOKEN));
((BindingProvider)port).getRequestContext().put(Message.PROTOCOL_HEADERS, extraHeader);

Tip 4: request soap header

Your soap services may required a soap header, just take a look to your wsdl file.

/* create and init the soap header object */
GoogleSoapHeader soapHeader = new GoogleSoapHeader();
//soapHeader.set...

/* Here the technical stuff related to cxf library: */
GoogleObjectFactory obj = new GoogleObjectFactory();
JAXBElement<GoogleSoapHeader> authToken = obj.createGoogleRequestHeader(soapHeader);

List<Header> headersList = new ArrayList<Header>();
headersList.add(new Header(authToken.getName(), authToken.getValue(), 
new JAXBDataBinding(GoogleSoapHeader.class)));
((BindingProvider)port).getRequestContext().put(Header.HEADER_LIST, headersList);

Tip 5: Enjoy!

You can now call the service.