1

I have a REST API exposed on the AWS infrastructure on the behalf of API Gateway. In a Lambda function in Java I need to call the associated endpoints. The AWS documentation recommends to generate a client using the API Gateway console. However, the generated client has several dozens of classes, perhaps even 100 ! Of course, this couldn't be the way.

Did anyone succeed to call API Gateway exposed endpoints using RESTeasy or CXF clients ? Or even Apache HTTP Client ?

Many thanks in advance.

Seymour Glass
  • 81
  • 2
  • 15
  • This is more a discussion than a question. I would recommend using Lambda Proxy Integration instead of the now "legacy" way of calling Lambda functions from API Gateway. This way you you do the path (endpoint) handling logic in your own code. Was a much better experience. – raupach Aug 11 '20 at 16:31
  • Are you just using the Swagger definitions to generate a Java client? I'm a bit confused as that has nothing to do with Lambda or API gateway. A highly complex API may indeed have 100's of classes generated though generally a well designed API should have much less, regardless of the implementation environment. – stdunbar Aug 11 '20 at 22:39
  • @BjörnRaupach You didn't understand the question. I don't call Lambda functions from API Gateway but the reverse, I'm calling endpoints exposed via API Gateway from Lamda functions. Please make sure you understand the question you're aswering to :-) – Seymour Glass Aug 12 '20 at 14:43
  • @stdunbar: since you're confused, I'll try to explain once again. This doesn't have anything to do with swagger and I don't know where from you've seen any reference to swagger. The API Gateway console has a dedicated function able to generate clients for the exposed endpoints. You can choose what language you want and you download a Java archive with 100 classes. This archive doesn't contain only the client to call the API but also a lot of other stuff you don't need and which makes this "client" unusable, in my opinion. Hence my question: did anyone use Resteasy or CXF for this purpose ? – Seymour Glass Aug 12 '20 at 14:51

1 Answers1

1

I'm answering my own question. Finally, I confirm that using JAX-RS clients works as expected with API Gateway. In my case, I preferred RESTeasy, but it should work with CXF as well or even with the Apache HTTp Client. Here is what I did:

Maven dependencies:

  ...
  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>org.jboss.resteasy</groupId>
        <artifactId>resteasy-bom</artifactId>
        <version>4.4.1.Final</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>
  ...
  <dependency>
    <groupId>org.jboss.resteasy</groupId>
    <artifactId>resteasy-client</artifactId>
    <version>4.4.1.Final</version>
    <exclusions>
      <exclusion>
        <groupId>org.jboss.spec.javax.xml.bind</groupId>
        <artifactId>jboss-jaxb-api_2.3_spec</artifactId>
      </exclusion>
      <exclusion>
        <groupId>com.sun.activation</groupId>
        <artifactId>jakarta.activation</artifactId>
      </exclusion>
    </exclusions>
  </dependency>
  <dependency>
    <groupId>org.jboss.resteasy</groupId>
    <artifactId>resteasy-jaxb-provider</artifactId>
    <exclusions>
      <exclusion>
        <groupId>org.jboss.spec.javax.xml.bind</groupId>
        <artifactId>jboss-jaxb-api_2.3_spec</artifactId>
      </exclusion>
      <exclusion>
        <groupId>com.sun.activation</groupId>
        <artifactId>jakarta.activation</artifactId>
      </exclusion>
    </exclusions>
  </dependency>
  <dependency>
    <groupId>org.jboss.resteasy</groupId>
    <artifactId>resteasy-jackson2-provider</artifactId>
  </dependency>
  ...

Please notice the exclusions meant to workaround the maven-shade-plugin which will overload different versions of the same artifacts.

maven-shade-plugin configuration:

...
<plugin>
  <artifactId>maven-shade-plugin</artifactId>
  <version>3.2.1</version>
  <executions>
    <execution>
      <phase>package</phase>
      <goals>
        <goal>shade</goal>
      </goals>
    </execution>
  </executions>
  <configuration>
    <finalName>...</finalName>
    <createDependencyReducedPom>false</createDependencyReducedPom>
      <!-- Using filtering in order to get rid of nasty warnings generated by shading module-info-->
      <filters>
        <filter>
          <artifact>*:*</artifact>
          <excludes>
            <exclude>module-info.class</exclude>
          </excludes>
        </filter>
      </filters>
      <!-- Required as per https://stackoverflow.com/questions/24023155-->
      <transformers>
        <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
        </transformers>
      </configuration>
    </plugin>
    ...

Java client code:

...
private static ResteasyClient client =  new ResteasyClientBuilderImpl().httpEngine(new URLConnectionEngine()).build();
private static WebTarget webTarget = client.target("https://...");
...
webTarget.request().post(Entity.entity(..., "application/json"));
...

Please notice that using JAX-RS pure client as below:

...
private static Client client = ClientBuilder.newClient();
...

won't work and will raise the following exception:

javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x7933f1c0: Failure in SSL library, usually a protocol error

Hence, in order to work around this, I needed to use RESTeasy (non JAX-RS) specific stuff, which isn't good. This is a RESTeasy bug and is supposed to have been solved in 4.5. However, due to some deprecations and refactorings (class ResteasyClientBuilderImpl doesn't exist any more, etc.) I preferred stay with the 4.4.

So, doing like this works as expected, the Lambda functions successfully call the REST endpoints exposed through API Gateway and I don't need to use the huge Java library generated with AWS console.

Seymour Glass
  • 81
  • 2
  • 15