# Overview

## Welcome to IC4J

Welcome to IC4J!&#x20;

IC4J is an Agent for the Internet Computer (IC4J) which is an Adapter that has a set of native Java libraries to allow remote connection of other systems to the Internet Computer Environment.

This is where you will find all the documentation to get up and running with the IC4J Application Programming Interface (API).

To learn more about the Internet Computer platform, please visit Dfinity website. <https://dfinity.org>

*"The Internet Computer is created by the Internet Computer Protocol (“ICP”), which has formed the world’s first web-speed, web-serving public blockchain. The Internet Computer is self-governing and can grow its capacity as required. It combines special node machines run en masse by independent data centers all around the world. Like all blockchains, it is unstoppable, and the code it hosts is tamperproof."*

{% embed url="<https://dfinity.org>" %}

{% embed url="<https://smartcontracts.org/docs/introduction/welcome.html>" %}

The IC4J code is the Java implementation of the Internet Computer Interface protocol.

{% embed url="<https://sdk.dfinity.org/docs/interface-spec/index.html>" %}

IC4J library is using Dfinity Rust Agent as an inspiration, using similar package structures and naming conventions.

{% embed url="<https://github.com/dfinity/agent-rs>" %}

The Internet Computer uses two Method types to execute smart contract code in the canister; UPDATE and QUERY.&#x20;

UPDATE method is mutable, allowing the user to change data on the chain.&#x20;

QUERY method is immutable, and does not allow the user to change the data.

&#x20;IC4J uses a native ICP binary protocol so that the Java code can participate in chain updates and query canister data without using any gateway or bridge.&#x20;

This way the communication between the Java application and the IC canister is secure and tamperproof.&#x20;

![](/files/Ga0E4baYjl6xryetXnHA)

IC4J source code with samples can be found on Github.

{% embed url="<https://github.com/ic4j>" %}

## Want to jump right in?

Jump in to the quick start docs section and make the first request:

{% content-ref url="/pages/7CVz4L9pYkR4WFE47WjC" %}
[Quick Start](/quick-start)
{% endcontent-ref %}

## Want to deep dive?

Dive a little deeper and start exploring our API reference to get an idea of everything that's possible with the API:

{% content-ref url="/pages/C7ihfe5KyWfWkRhmNpqN" %}
[API Reference](/reference/api-reference)
{% endcontent-ref %}


# Introduction

"The Internet Computer is the fastest and most scalable general-purpose blockchain. It extends the internet with computation. Smart contracts (dapps) can run 100% on the Internet Computer as it can serve web contents directly into browsers. Moreover, end users can seamlessly and securely interact with dapps on the Internet Computer. In particular, users in general do not need any tokens to use a dapp nor is it necessary for anyone to download blockchain state to verify correctness of transactions because of the Internet's Computer's groundbreaking chain key cryptography. Users can security authenticate to dapps using internet identity, the Internet Computer's anonymous blockchain authentication framework." https\:/dfinity.org/how it works

Some Definitions

Canister : A canister is **much like a process in an operating system like Linux, MacOS, or Windows**. The operating system keeps track of valid memory ranges for a process, while a canister has a boundary on its linear memory that's enforced by the Internet Computer

Canister ICP : Canisters are loaded with Cycles(gas) for Computation.\
\
ICP is burned to obtain cycles. **ICP tokens are used to mint cycles burned by canisters for computation, which acts as a deflationary force**.

NNS : One of the elements that makes ICP unique is the **Network Nervous System (NNS)**, which is responsible for controlling, configuring, and managing the network. Data centers join the network by applying to the NNS, which is responsible for inducting data centers.

SDK: Software Development KIt&#x20;

API : Application Development Interface

Adapter Pattern : Adapter pattern works as a bridge between two incompatible interfaces

Agent : Software agent, **a computer program that performs various actions continuously and autonomously on behalf of an individual or an organization**. For example, a software agent may archive various computer files or retrieve electronic messages on a regular schedule.

Method : method is a set of commands or statement which is written to perform a specific task.

Argument: An argument is a value passed to a function when the function is called. Whenever a function is called during the execution of the program, there are some values passed to the function. These values are called arguments.

&#x20;


# Quick Start

### Make your first Java call to the IC canister

To create your first IC canister, follow instructions from the Dfinity Quick Start location.

{% embed url="<https://smartcontracts.org/docs/quickstart/2-quickstart.html>" %}
Dfinity Quick Start
{% endembed %}

You can either use local installation of the Canister SDK or use ICP Ninja.

{% embed url="<https://icp.ninja/>" %}

If you create local project, it will implicitly create the first Motoko file [**main.mo**](https://github.com/ic4j/samples/blob/master/IC4JHelloWorld/src/main.mo). The code is a very simple HelloWorld application with one method named **greet***.*

{% code title="main.mo" %}

```javascript
actor {
  public func greet(name : Text) : async Text {
    return "Hello, " # name # "!";
  };
};
```

{% endcode %}

To run this canister code in [ICP Ninja](https://icp.ninja/) just copy and paste this source to the editor and click the **Deploy** button.

We can start building the first Java application, that will invoke **greet** method. The source of IC4JHelloWorld project can be found [here](https://github.com/ic4j/samples/tree/master/IC4JHelloWorld).

For your Java project you can use either Gradle or Maven build. To include IC4J support in your project include Gradle or Maven dependencies.&#x20;

{% tabs %}
{% tab title="Gradle" %}

```markup
implementation 'org.ic4j:ic4j-agent:0.8.0'
implementation 'org.ic4j:ic4j-candid:0.8.0'
```

{% endtab %}

{% tab title="Maven" %}

```xml
<dependency>
  <groupId>org.ic4j</groupId>
  <artifactId>ic4j-agent</artifactId>
  <version>0.8.0</version>
</dependency>
<dependency>
  <groupId>org.ic4j</groupId>
  <artifactId>ic4j-candid</artifactId>
  <version>0.8.0</version>
</dependency>
```

{% endtab %}
{% endtabs %}

Now we can start writing Java code. The easiest way to communicate with the Internet Computer **Canister** is to use **ProxyBuilder**.&#x20;

The ProxyBuilder module creates the Java proxy object Canister  based on Java interface with Canister annotations. You can find full source of this interface [here](https://github.com/ic4j/samples/blob/master/IC4JHelloWorld/src/main/java/org/ic4j/samples/helloworld/HelloWorldProxy.java).

{% code title="HelloWorldProxy.java" %}

```java
public interface HelloWorldProxy {	
	@UPDATE
	@Name("greet")
	@Waiter(timeout = 30)
	public CompletableFuture<String> greet(@Argument(Type.TEXT)String name);
}
```

{% endcode %}

Next, define the **Type of Method** for the Canister (UPDATE or QUERY), the **Name** of the method and define **Waiter** properties for **UPDATE** method.&#x20;

For method arguments we can also define **Candid** type.

First we have to create the **ReplicaTransport** object using the URL to your Canister (either local or remote). The we use AgentBuilder to create the **Agent Object**.&#x20;

To create the **Canister Proxy** object use ProxyBuilder *create* the method with the agent and the Canister Principal arguments and then *getProxy* method passing Java proxy class.

The full source can be found [here](https://github.com/ic4j/samples/blob/master/IC4JHelloWorld/src/main/java/org/ic4j/samples/helloworld/Main.java).

{% code title="Main.java" %}

```java
ReplicaTransport transport = ReplicaApacheHttpTransport.create(icLocation);
Agent agent = new AgentBuilder().transport(transport).build();			
HelloWorldProxy helloWorldProxy = ProxyBuilder.create(agent, Principal.fromString(icCanister))
					.getProxy(HelloWorldProxy.class);
String value = "world";		
CompletableFuture<String> proxyResponse = helloWorldProxy.greet(value);			
String output = proxyResponse.get();
```

{% endcode %}

Next, to call the Internet Computer Canister you will need 2 properties, **location URL** and **Canister ID.**&#x20;

This is an example to read those properties from the [*application.properties*](https://github.com/ic4j/samples/blob/master/IC4JHelloWorld/src/main/resources/application.properties) file.

{% code title="application.properties" %}

```java
ic.location=https://icp-api.io/
ic.canister=yaku6-4iaaa-aaaab-qacfa-cai
```

{% endcode %}

Replace those properties with ones from your deployed canister, either local or remote.

The **UPDATE** call will run asynchronously and return the Java [CompletableFuture](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html) object.

Next, the Java project can be built and run using **Gradle Script** [build.gradle](https://github.com/ic4j/samples/blob/master/IC4JHelloWorld/build.gradle). (***This build requires Java 1.8;*** if you are using a different version, make the necessary modifications in the script).&#x20;

This build script creates **Fat Ja**r with all the required dependencies.

```
gradle build
```

Next run with Java.

```
java -jar build/libs/ic4j-sample-helloworld-0.6.19.jar
```

The output should look like this.

```
[main] INFO org.ic4j.samples.helloworld.Main - Hello, world!
```


# License

The IC4J Agent is available under **Apache License 2.0.**


# API Reference

Dive into the specifics by checking out our complete documentation.

## Create ReplicaTransport Object

{% content-ref url="/pages/ypsKZMOtJ8FofSi7Oi2G" %}
[ReplicaTransport](/reference/api-reference/replicatransport)
{% endcontent-ref %}

## Create Identity Object

{% content-ref url="/pages/RB0HF3h16Axn281j8NqG" %}
[Identity](/reference/api-reference/identity)
{% endcontent-ref %}

## Create Principal Object

{% content-ref url="/pages/DQOjWKeqCwwSrm1SPrlE" %}
[Principal](/reference/api-reference/principal)
{% endcontent-ref %}

## Create Agent Object

{% content-ref url="/pages/cO7eXo12GPGkgDb7E8Hv" %}
[AgentBuilder](/reference/api-reference/agentbuilder)
{% endcontent-ref %}

## Create Canister Proxy Object

{% content-ref url="/pages/o9sUSjR5KS3TVD4oaDSR" %}
[ProxyBuilder](/reference/api-reference/proxybuilder)
{% endcontent-ref %}

## Using IDLArgs

{% content-ref url="/pages/9PCrVcoEP4JiFnbmz9Wu" %}
[Using IDLArgs](/reference/api-reference/using-idlargs)
{% endcontent-ref %}

## Using QueryBuilder and UpdateBuilder

{% content-ref url="/pages/uE8TJ2Iuncp3limL27HT" %}
[QueryBuilder and UpdateBuilder](/reference/api-reference/querybuilder-and-updatebuilder)
{% endcontent-ref %}

## Using Raw Agent Methods

{% content-ref url="/pages/ayz6J2ldthQmf47oZPVN" %}
[Using Raw Agent Methods](/reference/api-reference/using-raw-agent-methods)
{% endcontent-ref %}

## Handle Binary Payloads

{% content-ref url="/pages/zu72ZTuzaO6ND7IOXygC" %}
[Handle Binary Payloads](/reference/api-reference/handle-binary-payloads)
{% endcontent-ref %}

## Object Serializers and Deserializers

{% content-ref url="/pages/6I92HSH5TDS4TIbjKLDG" %}
[Object Serializers and Deserializers](/reference/api-reference/object-serializers-and-deserializers)
{% endcontent-ref %}

## Android Development

{% content-ref url="/pages/ye0i6JzfbkxwHdmAsGqr" %}
[Android Development](/reference/api-reference/android-development)
{% endcontent-ref %}


# Install IC4J Libraries

The best way to include IC4J libraries in the Java application project is to use **Gradle** or **Maven Imports** from **Maven Central**.

{% tabs %}
{% tab title="Gradle" %}

```
implementation 'org.ic4j:ic4j-agent:0.8.0'
implementation 'org.ic4j:ic4j-candid:0.8.0'
```

{% endtab %}

{% tab title="Maven" %}

```xml
<dependency>
  <groupId>org.ic4j</groupId>
  <artifactId>ic4j-agent</artifactId>
  <version>0.8.0</version>
</dependency>
<dependency>
  <groupId>org.ic4j</groupId>
  <artifactId>ic4j-candid</artifactId>
  <version>0.8.0</version>
</dependency>
```

{% endtab %}
{% endtabs %}


# Supported Types

The IC4J **Candid Library** allows Java developers to serialize and deserialize Java native types to **IC Candid IDL types.**

*"Candid is an interface description language. Its primary purpose is to describe the public interface of a **service**, usually in the form of a program deployed as a **canister smart contract** that runs on the Internet Computer. One of the key benefits of Candid is that it is language-agnostic, and allows inter-operation between services and front-ends written in different programming languages, including Motoko, Rust, and JavaScript."*

{% embed url="<https://smartcontracts.org/docs/candid-guide/candid-concepts.html>" %}
What is Candid?
{% endembed %}

{% embed url="<https://smartcontracts.org/docs/candid-guide/candid-types.html>" %}
Candid Types
{% endembed %}

This table shows implicit mapping between Candid types and default Java type assignment.

| Candid    | Java        |
| --------- | ----------- |
| bool      | Boolean     |
| int       | BigInteger  |
| int8      | Byte        |
| int16     | Short       |
| int32     | Integer     |
| int64     | Long        |
| nat       | BigInteger  |
| nat8      | Byte        |
| nat16     | Short       |
| nat32     | Integer     |
| nat64     | Long        |
| float32   | Float       |
| float64   | Double      |
| text      | String      |
| opt       | Optional    |
| principal | Principal   |
| vec       | array, List |
| record    | Map, Class  |
| variant   | Map, Enum   |
| func      | Func        |
| service   | Service     |
| null      | Null        |


# ReplicaTransport

In the context of the Internet Computer blockchain, a **Replica** refers to the Internet Computer protocol processes running on a node.

To be able to connect remotely to the Internet Computer Canister IC4J implements ReplicaTransport interface over different Java HTTP Client libraries. Developers can choose specific implementations based on their Java application use cases.

[ReplicaTransport](https://github.com/ic4j/ic4j-agent/blob/master/src/main/java/org/ic4j/agent/ReplicaTransport.java) interface currently supports 4 Internet Computer functions.&#x20;

Calls in [ReplicaTransport](https://github.com/ic4j/ic4j-agent/blob/master/src/main/java/org/ic4j/agent/ReplicaTransport.java) interface are asynchronous and return the [CompletableFuture](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html) response type.

```java
public interface ReplicaTransport {
    public CompletableFuture<byte[]> status();
    public CompletableFuture<byte[]> query(Principal canisterId, byte[] envelope);
    public CompletableFuture<byte[]> call(Principal canisterId, byte[] envelope, RequestId requestId);
    public CompletableFuture<byte[]> readState(Principal canisterId, byte[] envelope);
}
```

## Apache HTTP 5 Client transport implementation

The **Apache HTTP 5 library** is a robust, stable Java implementation of the HTTP protocol. It allows developers to define advanced features like connection pooling.

{% embed url="<https://hc.apache.org/httpcomponents-client-5.1.x/index.html>" %}

The simplest way to create [ReplicaTransport](https://github.com/ic4j/ic4j-agent/blob/master/src/main/java/org/ic4j/agent/ReplicaTransport.java) is to use [ReplicaApacheHttpTransport](https://github.com/ic4j/ic4j-agent/blob/master/src/main/java/org/ic4j/agent/http/ReplicaApacheHttpTransport.java) to create the Method with the **IC URL String** as a parameter.&#x20;

```java
ReplicaTransport transport = 
ReplicaApacheHttpTransport.create("http://localhost:4943/");
```

For advanced use cases, for example, to create Java server type applications handling a large number of clients and canisters, additional parameters can be defined.

<table><thead><tr><th width="206.28690807799444">Parameter</th><th></th></tr></thead><tbody><tr><td>url</td><td>Canister URL</td></tr><tr><td>maxTotal</td><td>Maximum total connections</td></tr><tr><td>maxPerRoute</td><td>Maximum connections per route</td></tr><tr><td>connectionTimeToLive</td><td>Time to live for connection in seconds</td></tr><tr><td>timeout</td><td>Connection timeout in seconds</td></tr></tbody></table>

```java
ReplicaTransport transport = 
ReplicaApacheHttpTransport.create("http://localhost:4943/", maxTotal, maxPerRoute,
 connectionTimeToLive, int timeout);
```

For even more complex scenarios ReplicaTransport can be created with the explicitly defined Apache HTTP Client connection manager [AsyncClientConnectionManager](https://hc.apache.org/httpcomponents-client-5.1.x/current/httpclient5/apidocs/org/apache/hc/client5/http/nio/AsyncClientConnectionManager.html).

```
ReplicaTransport transport = 
ReplicaApacheHttpTransport.create("http://localhost:4943/",asyncClientConnectionManager, int timeout);
```

## OkHttp Client transport implementation

For Android development it is recommended to use the **OkHttp Client Implementation**.&#x20;

OkHttp is an efficient HTTP & HTTP/2 client for Android and Java applications.

{% embed url="<https://square.github.io/okhttp>" %}

Use [ReplicaOkHttpTransport](https://github.com/ic4j/ic4j-agent/blob/master/src/main/java/org/ic4j/agent/http/ReplicaOkHttpTransport.java) to create the Method with the **IC URL String** as a parameter to create OkHttp ReplicaTransport

```java
ReplicaTransport transport = 
ReplicaOkHttpTransport.create("http://localhost:4943/");
```

If needed, the **Connection Timeout** can be explicitly defined : &#x20;

```java
ReplicaTransport transport = 
ReplicaOkHttpTransport.create("http://localhost:4943/", timeout);
```

## Java 11 HTTP Client transport implementation

From Java version 11 and higher, Oracle significantly improved functionality of Java default HTTP Client.&#x20;

To make core libraries compatible with Java version 1.8, it is recommended that this version of **transport**  is explicitly imported in the Graven or Maven build script.&#x20;

{% tabs %}
{% tab title="Gradle" %}

```
implementation 'org.ic4j:ic4j-java11transport:0.8.0'
```

{% endtab %}

{% tab title="Maven" %}

```xml
<dependency>
    <groupId>org.ic4j</groupId>
    <artifactId>ic4j-java11transport</artifactId>
    <version>0.8.0</version>
</dependency>
```

{% endtab %}
{% endtabs %}

Use [ReplicaJavaHttpTransport](https://github.com/ic4j/ic4j-java11transport/blob/master/src/main/java/org/ic4j/agent/http/ReplicaJavaHttpTransport.java) to create the Method with the **IC URL String** as a parameter to create **Java 11 ReplicaTransport**

```java
ReplicaTransport transport = 
ReplicaJavaHttpTransport.create("http://localhost:4943/");
```

If needed the connection timeout can be defined explicitly.

```java
ReplicaTransport transport = 
ReplicaJavaHttpTransport.create("http://localhost:4943/", timeout);
```

###


# Identity

IC4J Java Agent currently supports 3 different identity mechanisms. To learn more about the Internet Computer identity mechanisms refer to the Dfinity [documentation](https://smartcontracts.org/docs/interface-spec/index.html).

IC4J Agent uses the open source Java cryptography library [Bouncy Castle ](https://www.bouncycastle.org/java.html)in its implementation.&#x20;

If [BasicIndentity](https://github.com/ic4j/ic4j-agent/blob/master/src/main/java/org/ic4j/agent/identity/BasicIdentity.java) or [Secp256k1Identity](https://github.com/ic4j/ic4j-agent/blob/master/src/main/java/org/ic4j/agent/identity/Secp256k1Identity.java) is being used, define **Bouncy Castle** as the Java security provider in the code, before an Identity is created.

```java
Security.addProvider(new BouncyCastleProvider());
```

## AnonymousIdentity

AnonymousIdentity is the default mechanism in the IC4J Agent ; this means that if the identity is not specified explicitly , [AnonymousIdentity](https://github.com/ic4j/ic4j-agent/blob/master/src/main/java/org/ic4j/agent/identity/AnonymousIdentity.java) will be assigned implicitly.

To explicitly create the [AnonymousIdentity](https://github.com/ic4j/ic4j-agent/blob/master/src/main/java/org/ic4j/agent/identity/AnonymousIdentity.java) object, the **AnonymousIdentity Constructor** can be used.

```java
Identity identity = new AnonymousIdentity();
```

## BasicIdentity (ED25519)

The Internet Computer provides support for [ED25519](https://ed25519.cr.yp.to/) signatures. The [**dfx**](https://smartcontracts.org/docs/developers-guide/cli-reference/dfx-parent.html) **tool** can be used to generate the identity **PEM file**.

```
dfx identity new alice
cp ~/.config/dfx/identity/xxx/identity.pem alice.pem
```

Either the Java [Reader ](https://docs.oracle.com/javase/8/docs/api/java/io/Reader.html)or Java[ Path](https://docs.oracle.com/javase/8/docs/api/java/nio/file/Path.html) can be used to read the ED22219 PEM resource to create the [BasicIdentity](https://github.com/ic4j/ic4j-agent/blob/master/src/main/java/org/ic4j/agent/identity/BasicIdentity.java) object.

```java
Reader sourceReader = new InputStreamReader(Main.class.getClassLoader().getResourceAsStream(ED25519_IDENTITY_FILE));
identity = BasicIdentity.fromPEMFile(sourceReader);
```

```java
Path path = Paths.get(getClass().getClassLoader().getResource(ED25519_IDENTITY_FILE).getPath());
Identity identity = BasicIdentity.fromPEMFile(path);
```

Another option is to use Java [KeyPair](https://docs.oracle.com/javase/8/docs/api/java/security/KeyPair.html) as an input parameter.

```java
KeyPair keyPair = KeyPairGenerator.getInstance("Ed25519").generateKeyPair();
Identity identity = BasicIdentity.fromKeyPair(keyPair);
```

The Java byte\[] array can also be used as an input parameter.

```java
byte[] input;
Identity identity = BasicIdentity.fromPEM(input);
```

## Secp256k1Identity

The Internet Computer also supports [Secp256k1](https://en.bitcoin.it/wiki/Secp256k1) signatures commonly used with Bitcoin or Ethereum.

Either Java [Reader ](https://docs.oracle.com/javase/8/docs/api/java/io/Reader.html)or Java[ Path](https://docs.oracle.com/javase/8/docs/api/java/nio/file/Path.html) can be used to read the Secp256k1 PEM resource to create the [Secp256k1Identity](https://github.com/ic4j/ic4j-agent/blob/master/src/main/java/org/ic4j/agent/identity/Secp256k1Identity.java) object.

```java
Reader sourceReader = new InputStreamReader(Main.class.getClassLoader().getResourceAsStream(ED25519_IDENTITY_FILE));
identity = Secp256k1Identity.fromPEMFile(sourceReader);
```

```java
Path path = Paths.get(getClass().getClassLoader().getResource(ED25519_IDENTITY_FILE).getPath());
Identity identity = Secp256k1Identity.fromPEMFile(path);
```

Another option is to use Java [KeyPair](https://docs.oracle.com/javase/8/docs/api/java/security/KeyPair.html) as an input parameter.

```java
Identity identity = Secp256k1Identity.fromKeyPair(keyPair);
```

To see a fully functional Java sample with all 3 Identity mechanisms refer to this Github [sample](https://github.com/ic4j/samples/tree/master/IC4JIdentitySample).


# Principal

A principal is an entity that can be authenticated by the Internet Computer blockchain. Principals that interact with the Internet Computer blockchain often do so via an identity.

To create a [Principal](https://github.com/ic4j/ic4j-candid/blob/master/src/main/java/org/ic4j/types/Principal.java) object in Java one of these static methods can be used.&#x20;

1\) To create Principal from Java String object.

```java
Principal principal = Principal.fromString(stringValue);
```

2\) To create Principal from Java byte\[] array object.

```java
Principal principal = Principal.from(byteArrayValue);
```

3\) To create Management Canister Principal.

```java
Principal principal = Principal.managementCanister() ;
```

4\) To create Anonymous Principal.

```java
Principal principal = Principal.anonymous() ;
```

5\) To create Self Authenticating Principal from public key byte\[] array object.

```java
Principal principal = Principal.selfAuthenticating(publicKeyByteArrayValue) ;
```


# AgentBuilder

To create an [Agent](https://github.com/ic4j/ic4j-agent/blob/master/src/main/java/org/ic4j/agent/Agent.java) Java object the [AgentBuilder](https://github.com/ic4j/ic4j-agent/blob/master/src/main/java/org/ic4j/agent/AgentBuilder.java) build method is used.&#x20;

1\) Use transport method passing [ReplicaTransport](/reference/api-reference/replicatransport) parameter.

```java
new AgentBuilder().transport(replicaTransport);
```

2\) Use identity method passing [Identity](/reference/api-reference/identity) parameter.

```java
new AgentBuilder().identity(identity)
```

3\) IngresExpiry provides a default ingress expiry. This is the delta that will be applied at the time an update or query is made. Use Java [Duration](https://docs.oracle.com/javase/8/docs/api/java/time/Duration.html) type parameter.

```java
new AgentBuilder().ingresExpiry(Duration.ofSeconds(300));
```

4\) Creation of an Agent object.

```java
Agent agent = new AgentBuilder().transport(replicaTransport)
.identity(identity)
.ingresExpiry(Duration.ofSeconds(300))
.build();
```


# ProxyBuilder

Using ProxyBuilder is the easiest way to make calls to the Internet Computer using the IC4J Agent. ProxyBuilder will use the Java interface with IC4J annotations which represent the Internet Computer Canister.

The Internet Computer Canister and its Methods will create a proxy object which implements the defined interface.&#x20;

ProxyBuilder will then provide all Candid type serialization and deserialization steps and the execution of specified canister methods.

Here is an example using Motoko [canister](https://github.com/ic4j/samples/blob/master/IC4JHelloWorldAdvanced/src/main.mo) with one QUERY and one UPDATE method.

{% code title="main.mo" %}

```javascript
actor {
    stable var name = "Me";

    public func greet(value : Text) : async Text {
        name := value;
        return "Hello, " # name # "!";
    };

    public shared query func peek() : async Text {
        return name;
    };    
};
```

{% endcode %}

The Java Proxy interface for this canister looks like [this](https://github.com/ic4j/samples/blob/master/IC4JHelloWorldAdvanced/src/main/java/org/ic4j/samples/helloworld/HelloWorldProxy.java).

{% code title="HelloWorldProxy.java" %}

```java
public interface HelloWorldProxy {	
	@UPDATE
	@Name("greet")
	@Waiter(timeout = 30)
	public CompletableFuture<String> greet(@Argument(Type.TEXT)String name);
	
	@QUERY
	@Name("peek")
	public String peek();
}
```

{% endcode %}

To define if the method is QUERY or UPDATE use [@QUERY](https://github.com/ic4j/ic4j-agent/blob/master/src/main/java/org/ic4j/agent/annotations/QUERY.java) or [@UPDATE](https://github.com/ic4j/ic4j-agent/blob/master/src/main/java/org/ic4j/agent/annotations/UPDATE.java) annotations.&#x20;

The annotation @Name is optional, but if not specified, the ProxyBuilder will implicitly use the name of the Java method.

For the UPDATE method the developer can explicitly define the Waiter object with [@Waiter](https://github.com/ic4j/ic4j-agent/blob/master/src/main/java/org/ic4j/agent/annotations/Waiter.java) annotation, which will check the state of the UPDATE operation in certain intervals, defined  by the sleep property. The default value for the sleep property is set to 5 seconds.&#x20;

The developer can also define the timeout property, to specify when the Waiter should keep checking the state.&#x20;

The default value for the timeout property is set to 60 seconds. If the annotation is not specified, the ProxyBuilder will automatically set default values.

For Method parameters the developer can also set a Candid type of the argument with the [@Argument ](https://github.com/ic4j/ic4j-agent/blob/master/src/main/java/org/ic4j/agent/annotations/Argument.java)annotation. If this annotation is not defined, the ProxyBuilder will use the default Java to Candid [mapping](/reference/api-reference/supported-types).

Here is an example of how to create a proxy object in Java [code](https://github.com/ic4j/samples/blob/master/IC4JHelloWorldAdvanced/src/main/java/org/ic4j/samples/helloworld/Main.java).

{% code title="Main.java" %}

```java
Agent agent = new AgentBuilder().transport(transport).identity(identity).build();			
			
HelloWorldProxy helloWorldProxy = ProxyBuilder.create(agent, Principal.fromString(icCanister))
					.getProxy(HelloWorldProxy.class);rr
```

{% endcode %}

The **ProxyBuilder Create Method** will accept 2 arguments, **Agent and Principal.**&#x20;

The **getProxy Method** will use the **proxy interface class** as an argument.&#x20;

The call to the canister can now be completed by calling any other Java function.&#x20;

{% code title="" %}

```java
String output = helloWorldProxy.peek();

String value = "world";			
CompletableFuture<String> proxyResponse = helloWorldProxy.greet(value);
output = proxyResponse.get();
```

{% endcode %}

The **UPDATE** function call is executed asynchronously, returning  the Java [CompletableFuture](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html) result.

The full source code of this sample can be found [here](https://github.com/ic4j/samples/tree/master/IC4JHelloWorldAdvanced).

{% code title="LoanBroker.java" %}

```java
@Agent(identity = @Identity(type = IdentityType.BASIC, pem_file = "/cert/Ed25519_identity.pem"), transport = @Transport(url = "http://localhost:4943/"))
@Canister("rrkah-fqaaa-aaaaa-aaaaq-cai")
@EffectiveCanister("rrkah-fqaaa-aaaaa-aaaaq-cai")
public interface LoanBroker {
	@UPDATE
	@Name("apply")
	@Waiter(timeout = 30)
	@ResponseClass(LoanOffer.class)
	public CompletableFuture<LoanOffer> apply(@Argument(Type.RECORD)LoanApplication application);
}
```

{% endcode %}

{% code title="LoanBroker.java" %}

```java
@Agent(identity = @Identity(type = IdentityType.BASIC, pem_file = "/cert/Ed25519_identity.pem"), transport = @Transport(url = "http://localhost:4943/"))
@Canister("rrkah-fqaaa-aaaaa-aaaaq-cai")
@EffectiveCanister("rrkah-fqaaa-aaaaa-aaaaq-cai")
public interface LoanBroker {
	@UPDATE
	@Name("apply")
	@Waiter(timeout = 30)
	@ResponseClass(LoanOffer.class)
	public CompletableFuture<LoanOffer> apply(@Argument(Type.RECORD)LoanApplication application);
}
```

{% endcode %}

Developers can optionally use the following additional annotations.

Use the  [@Agent](https://github.com/ic4j/ic4j-agent/blob/master/src/main/java/org/ic4j/agent/annotations/Agent.java) annotation to define Identity and Transport properties directly in the proxy interface.

Use the  [@Canister](https://github.com/ic4j/ic4j-agent/blob/master/src/main/java/org/ic4j/agent/annotations/Canister.java) annotation to define canister id.

Use the  [@EffectiveCanister](https://github.com/ic4j/ic4j-agent/blob/master/src/main/java/org/ic4j/agent/annotations/EffectiveCanister.java) annotation to define effective canister id.

If the **Complex Type Response** is being used with Java class needing to be defined, and deserializing is necessary,  use the @ResponseClass annotation.&#x20;


# Using IDLArgs

To create the binary form of Candid data in Java or to convert data from candid binary form to Java use the [IDLArgs](https://github.com/ic4j/ic4j-candid/blob/master/src/main/java/org/ic4j/candid/parser/IDLArgs.java) class.

This is how to create a byte\[] array from a List of [IDLValue](https://github.com/ic4j/ic4j-candid/blob/master/src/main/java/org/ic4j/candid/parser/IDLValue.java).&#x20;

[IDLValue](https://github.com/ic4j/ic4j-candid/blob/master/src/main/java/org/ic4j/candid/parser/IDLValue.java) is a wrapped value, consisting of the Java value and the  [IDLType](https://github.com/ic4j/ic4j-candid/blob/master/src/main/java/org/ic4j/candid/parser/IDLType.java).

```java
List<IDLValue> args = new ArrayList<IDLValue>();
BigInteger intValue = new BigInteger("10000");
args.add(IDLValue.create(intValue));
IDLArgs idlArgs = IDLArgs.create(args);
byte[] payload = idlArgs.toBytes();
```

To convert data from byte\[] array to IDLArgs use the Method **fromBytes**.

```java
IDLArgs outArgs = IDLArgs.fromBytes(output);
```

When dealing with Complex Types, consider defining IDLTypes , a useful way for deserialization.&#x20;

```java
IDLType[] idlTypes = { idlValue.getIDLType() };
IDLArgs outArgs = IDLArgs.fromBytes(output, idlTypes);
```

## IDLType

[IDLType](https://github.com/ic4j/ic4j-candid/blob/master/src/main/java/org/ic4j/candid/parser/IDLType.java) class is a wrapper for Candid type definition. Use **createType** method to create a Java object.

For simple Candid types use only the [Type](https://github.com/ic4j/ic4j-candid/blob/master/src/main/java/org/ic4j/candid/types/Type.java) argument.

```java
IDLType idlType = IDLType.createType(Type.INT);
```

When creating VEC or OPT Candid types, the **inner type** needs to  be defined.&#x20;

The inner type can also have **nested types**. &#x20;

```java
IDLType idlArrayType = IDLType.createType(Type.VEC,Type.INT);
IDLType idlOptionalType = IDLType.createType(Type.OPT,Type.INT);
```

When creating the RECORD or VARIANT Candid types, the Type Map needs to be defined.&#x20;

Type Map can also have nested types.

The key in **Type Map** is the [Label](https://github.com/ic4j/ic4j-candid/blob/master/src/main/java/org/ic4j/candid/types/Label.java) type. **Label** can be *Named, Unnamed or Id type*.

```java
Map<Label, Object> typesMap = new HashMap<Label, Object>();
mapValue.put(Label.createNamedLabel("foo"), IDLType.createType(Type.INT));
IDLType idlType = IDLType.createType(Type.RECORD,typesMap);
```

To create the [IDLType](https://github.com/ic4j/ic4j-candid/blob/master/src/main/java/org/ic4j/candid/parser/IDLType.java) directly from Java class or object use the helper methods.&#x20;

These will automatically identify the default Candid type for Java class or object.

```java
IDLType idlType = IDLType.createType(Integer.class);
```

```java
BigInteger value = new BigInteger("100000000");
IDLType idlType = IDLType.createType(value);
```

To override **default type** use this variant.

```java
IDLType idlType = IDLType.createType(value, Type.NAT);
```

## IDLValue

To create the IDLValue Java object use the **Method** **Create** functon.&#x20;

This method has several variants, in if the **explicit type** definition is required.

To get the Java object value from IDLValue use the **Method** **getValue** function.

```java
BigInteger value = idlValue.getValue();
```


# QueryBuilder and UpdateBuilder

Another option to call the Internet Computer canisters from Java is to use **QueryBuilder** and **UpdateBuilder**.&#x20;

Use these options if direct manipulation with Candid data is required or there is a requirement for dynamic invocation.

Create byte\[] array binary Candid payload as an input argument using [IDLArgs](/reference/api-reference/using-idlargs).

```java
List<IDLValue> args = new ArrayList<IDLValue>();
BigInteger intValue = new BigInteger("10000");
args.add(IDLValue.create(intValue));
IDLArgs idlArgs = IDLArgs.create(args);
byte[] payload = idlArgs.toBytes();
```

## QueryBuilder

[QueryBuilder](https://github.com/ic4j/ic4j-agent/blob/master/src/main/java/org/ic4j/agent/QueryBuilder.java) **Method create** has 3 arguments, agent, canister id principal and method name.&#x20;

Optionally, the **expiration time** can be set using Methods **expireAfter** or **expireAt.**&#x20;

Pass binary payload as a parameter of **arg** method and execute using **Method** **call**.

```java
CompletableFuture<byte[]> response = QueryBuilder
	.create(agent, Principal.fromString(canisterid), "echoInt")
	.expireAfter(Duration.ofMinutes(3))
	.arg(payload)
	.call();
```

## UpdateBuilder

[UpdateBuilder](https://github.com/ic4j/ic4j-agent/blob/master/src/main/java/org/ic4j/agent/UpdateBuilder.java) uses very similar syntax to Method **create,** but has one extra method, **callAndWait ,**&#x69;f explicit [Waiter](https://github.com/ic4j/ic4j-agent/blob/master/src/main/java/org/ic4j/agent/Waiter.java) definition is required.

```java
CompletableFuture<byte[]> response = UpdateBuilder
	.create(agent, Principal.fromString(canisterid), "greet")
	.expireAfter(Duration.ofMinutes(3))
	.arg(payload)
	.callAndWait(Waiter.create(60, 5));
```

Use this to convert response payload to Java objects from binary Candid response payload.

```java
byte[] output = response.get();
IDLArgs outArgs = IDLArgs.fromBytes(output);
```


# Using Raw Agent Methods

Another option to invoke QUERY and UPDATE canister methods from Java is to use raw [Agent](https://github.com/ic4j/ic4j-agent/blob/master/src/main/java/org/ic4j/agent/Agent.java) methods **queryRaw** and **updateRaw**.

```java
CompletableFuture<byte[]> response = agent
    .queryRaw(Principal.fromString(canisterId),
        Principal.fromString(effectiveCanisterId),
         "echoInt",
          payload,
          ingressExpiryDatetime);
```

```java
CompletableFuture<byte[]> response = agent
    .updateRaw(Principal.fromString(canisterId),
        Principal.fromString(effectiveCanisterId),
         "greetjav",
          payload,
          ingressExpiryDatetime);
```

To get the status of the Internet Computer, use **status** Agent method. It will return the [Status](https://github.com/ic4j/ic4j-agent/blob/master/src/main/java/org/ic4j/agent/Status.java) Java type as follows.

```java
Status status = agent.status().get();
```


# Handle Binary Payloads

The Internet Computer also allows developers to send and receive binary data like JPG or PNG images.

A fully functional example of how to use IC4J API to call a Canister method with **binary payload** can be found [here](https://github.com/ic4j/samples/tree/master/IC4JImageSample).

This is an example to use Motoko to call the canister. [canister code](https://github.com/ic4j/samples/blob/master/IC4JImageSample/src/main.mo)&#x20;

The canister will receive a binary payload in **add** function and stores it. The Function **get** then returns the stored payload.

The Binary payload type is an array of Nat8.

{% code title="main.mo" %}

```javascript
actor {
  let images = Map.HashMap<Text, Blob>(0, Text.equal, Text.hash);
  
  public func add(name : Text, image : [Nat8]) : async Text {
    let blob : Blob = Blob.fromArray(image);
    Debug.print("Source Image Size " #debug_show(blob.size()));
    images.put(name, blob );
    return  name;
  };

  public query func get(name : Text) : async [Nat8] {
    let blob : ?Blob = images.get(name);
    switch blob {
            case (null) { return [] };
            case (?image) { 
              Debug.print("Result Image Size " #debug_show(image.size()));
              Blob.toArray(image);
               };
        };  
  };
};
```

{% endcode %}

In Java the [proxy interface](/reference/api-reference/proxybuilder) [ImageProxy](https://github.com/ic4j/samples/blob/master/IC4JImageSample/src/main/java/org/ic4j/samples/image/ImagesProxy.java) is created with the 2 methods **get** and **add**.

{% code title="ImagesProxy.java" %}

```java
public interface ImagesProxy {	
	@QUERY
	@Name("get")
	public byte[] get(@Argument(Type.TEXT)String name );	
	
	@UPDATE
	@Name("add")
	@Waiter(timeout = 30)
	public CompletableFuture<String> add(@Argument(Type.TEXT)String name, @Argument(Type.NAT8)byte[] image);
}
```

{% endcode %}

Then in a simple Java class , [ProxyBuilder](/reference/api-reference/proxybuilder) can be used to create Canister Java proxy.&#x20;

The source can be found in [Main.java](https://github.com/ic4j/samples/blob/master/IC4JImageSample/src/main/java/org/ic4j/samples/image/Main.java) file.

{% code title="Main.java" %}

```java
byte[] image = getImage(IMAGE_FILE, "png");
		
String name  = IMAGE_FILE;
ImagesProxy images = ProxyBuilder.create(agent, Principal.fromString(icCanister))
				.getProxy(ImagesProxy.class);		
CompletableFuture<String> proxyResponse = images.add(name, image);

String output = proxyResponse.get();		
byte[] imageResult = images.get(name);	
```

{% endcode %}

Binary Candid payload (\[Nat8]) can be represented in Java either as byte\[] array or Byte\[] array.


# Object Serializers and Deserializers

To handle complex Candid types RECORD and VARIANT IC4J use custom [ObjectSerializer](https://github.com/ic4j/ic4j-candid/blob/master/src/main/java/org/ic4j/candid/ObjectSerializer.java) and [ObjectDeserializer](https://github.com/ic4j/ic4j-candid/blob/master/src/main/java/org/ic4j/candid/ObjectDeserializer.java) implementations.&#x20;

If required, developers can design their own serializers and deserializers.&#x20;

The IC4J library comes with several implementations of the most common scenarios (Java Pojo, JSON, XML, JDBC).

Use Pojo Serializer and Deserializer to handle plain Java objects.

{% content-ref url="/pages/fFNdna5rDbxBelXg2vGd" %}
[Pojo Serializer and Deserializer](/reference/api-reference/object-serializers-and-deserializers/pojo-serializer-and-deserializer)
{% endcontent-ref %}

Use JSON Jackson Serializer and Deserializer to handle Jackson JSON objects.

{% content-ref url="/pages/2yGa1TAtAoxqCEOpzw9R" %}
[JSON Jackson Serializer and Deserializer](/reference/api-reference/object-serializers-and-deserializers/json-jackson-serializer-and-deserializer)
{% endcontent-ref %}

Use JSON Gson Serializer and Deserializer to handle Gson JSON objects.

{% content-ref url="/pages/2XTHGvZupk7G1Xd291DM" %}
[JSON Gson Serializer and Deserializer](/reference/api-reference/object-serializers-and-deserializers/json-gson-serializer-and-deserializer)
{% endcontent-ref %}

Use XML Serializer and Deserializer to handle XML DOM objects.

{% content-ref url="/pages/3XU4Sv1egy2hcws2k5pC" %}
[XML DOM Serializer and Deserializer](/reference/api-reference/object-serializers-and-deserializers/xml-dom-serializer-and-deserializer)
{% endcontent-ref %}

Use JDBC Serializer to handle JDBC objects.

{% content-ref url="/pages/GKY4zfZwzNNievUtS6Vz" %}
[JDBC Serializer](/reference/api-reference/object-serializers-and-deserializers/jdbc-serializer)
{% endcontent-ref %}


# Pojo Serializer and Deserializer

Use [PojoSerializer](https://github.com/ic4j/ic4j-candid/blob/master/src/main/java/org/ic4j/candid/pojo/PojoSerializer.java) and [PojoDeserializer](https://github.com/ic4j/ic4j-candid/blob/master/src/main/java/org/ic4j/candid/pojo/PojoDeserializer.java) to serialize and deserialize the annotated POJO (Plain Old Java Object) to and from Candid payload of type RECORD.&#x20;

Serializer and Deserializer will use Candid Java annotations to get the Candid Name and Type.&#x20;

A fully functional example using [PojoSerializer](https://github.com/ic4j/ic4j-candid/blob/master/src/main/java/org/ic4j/candid/pojo/PojoSerializer.java) and [PojoDeserializer](https://github.com/ic4j/ic4j-candid/blob/master/src/main/java/org/ic4j/candid/pojo/PojoDeserializer.java) can be found [here](https://github.com/ic4j/samples/tree/master/IC4JPojoSample).

This example calls a canister using Motoko [main.mo](https://github.com/ic4j/samples/blob/master/IC4JPojoSample/src/main.mo).&#x20;

The canister uses 2 complex types, **LoanApplication** and **LoanOffer.**

```javascript
 // Loan Application
public type LoanApplication = {
    id: Nat;
    firstname: Text;
    lastname: Text;
    zipcode: Text;
    ssn: Text;
    amount: Float;
    term: Nat16;
    created: Int;
 };

// Loan Offer
public type LoanOffer = {
    providerid: Principal;
    providername: Text;
    applicationid: Nat;
    apr: Float;
    created: Int;
};
```

The canister has 2 methods **apply** and **getOffers.**

```javascript
 public shared (msg) func apply(input : LoanApplication) : async LoanOffer { 
       counter += 1;
        Debug.print("Loan Application for user " #Principal.toText(msg.caller));
        
        let offer  : LoanOffer = {
            providerid = Principal.fromActor(this);
            providername = "Loan Provider";
            applicationid = counter;
            apr = 3.14;
            created = Time.now();
        };

        var userOffers :  ?Offers<LoanOffer> = offers.get(msg.caller);

        switch userOffers {
            case (null) { var userOffer : Offers<LoanOffer> = Buffer.Buffer(0); userOffer.add(offer);  offers.put(msg.caller, userOffer)};
            case (?userOffer) { userOffer.add(offer); };
        };
        return offer;
};

public query (msg) func getOffers() : async [LoanOffer] {
        var userOffers :  ?Offers<LoanOffer> = offers.get(msg.caller);

        switch userOffers {
            case (null) { return [] };
            case (?userOffer) { return userOffer.toArray() };
        };
};
```

To call this canister the annotated proxy Java interface [LoanProxy.java](https://github.com/ic4j/samples/blob/master/IC4JPojoSample/src/main/java/org/ic4j/samples/pojo/LoanProxy.java) and [ProxyBuilder](/reference/api-reference/proxybuilder) will be used.&#x20;

{% code title="LoanProxy.java" %}

```java
public interface LoanProxy {
	@UPDATE
	@Name("apply")
	@Waiter(timeout = 30)
	@ResponseClass(LoanOffer.class)
	public CompletableFuture<LoanOffer> apply(@Argument(Type.RECORD) LoanApplication loanApplication);
	
	@QUERY
	@Name("getOffers")
	public LoanOffer[] getOffers();
}
```

{% endcode %}

LoanApplication and LoanOffer Java classes with the Candid annotation are defined in [LoanApplication.java](https://github.com/ic4j/samples/blob/master/IC4JPojoSample/src/main/java/org/ic4j/samples/pojo/LoanApplication.java) and [LoanOffer.java](https://github.com/ic4j/samples/blob/master/IC4JPojoSample/src/main/java/org/ic4j/samples/pojo/LoanOffer.java).

{% code title="LoanApplication.java" %}

```java
public class LoanApplication{
    @Field(Type.NAT)
    public BigInteger id;
    public Double amount;
    @Field(Type.NAT16)    
    public Short term;
    @Name("firstname")
    public String firstName;
    @Name("lastname")
    public String lastName;
    public String ssn;
    public String zipcode;
    public BigInteger created;
}
```

{% endcode %}

{% code title="LoanOffer.java" %}

```java
public class LoanOffer{
    @Field(Type.PRINCIPAL)
    @Name("providerid")
    public String providerId;	
    @Name("providername")
    public String providerName;    
    @Field(Type.PRINCIPAL)
    @Name("userid")
    public Principal userId;
    @Field(Type.NAT)
    @Name("applicationid")
    public Integer applicationId;
    public Double apr;
    @Field(Type.INT)
    public Long created;
}
```

{% endcode %}

By default, **PojoSerializer** and **PojoDeserializer** will use [Java to Candid type mapping](/reference/api-reference/supported-types) and use the Java member variable name as the name of the Candid RECORD field.&#x20;

Use Candid annotations [@Field](https://github.com/ic4j/ic4j-candid/blob/master/src/main/java/org/ic4j/candid/annotations/Field.java) to override the default type and [@Name](https://github.com/ic4j/ic4j-candid/blob/master/src/main/java/org/ic4j/candid/annotations/Name.java) to override the default name.

To skip serialization and deserialization of certain member variables, use the [@Ignore](https://github.com/ic4j/ic4j-candid/blob/master/src/main/java/org/ic4j/candid/annotations/Ignore.java) annotation.

[ProxyBuilder](/reference/api-reference/proxybuilder) will implicitly use PojoSerializer and PojoDeserializer to convert Candid RECORD to a Java object.

{% code title="Main.java" %}

```java
LoanApplication loanApplication = new LoanApplication();
loanApplication.firstName = "John";
loanApplication.lastName = "Doe";
loanApplication.ssn = "111-11-1111";
loanApplication.term = 48;
loanApplication.zipcode = "95134";		
loanApplication.amount = (double) 20000.00;
loanApplication.id = new BigInteger("11");
loanApplication.created = new BigInteger("0");
		
LoanProxy loanProxy = ProxyBuilder
		.create(agent, Principal.fromString(icCanister))
		.getProxy(LoanProxy.class);
		
CompletableFuture<LoanOffer> response = loanProxy.apply(loanApplication);		
LoanOffer loanOffer = response.get();				
LOG.info("Loan Offer APR is " + loanOffer.apr);		
```

{% endcode %}

To use [Raw methods](/reference/api-reference/using-raw-agent-methods) or [QueryBuilder](/reference/api-reference/querybuilder-and-updatebuilder#querybuilder) and [UpdateBuilder](/reference/api-reference/querybuilder-and-updatebuilder#updatebuilder) use PojoSerializer and PojoDeserializer directly in the Java code.

{% code title="Main.java" %}

```java
IDLValue idlValue = IDLValue.create(loanApplication, new PojoSerializer());
List<IDLValue> args = new ArrayList<IDLValue>();
args.add(idlValue);
IDLArgs idlArgs = IDLArgs.create(args);

byte[] payload = idlArgs.toBytes();

CompletableFuture<byte[]> response = UpdateBuilder
	.create(agent, Principal.fromString(canisterid), "apply")
	.expireAfter(Duration.ofMinutes(3))
	.arg(payload)
	.callAndWait(Waiter.create(60, 5));
	
byte[] output = queryResponse.get();

LoanOffer loanOffer = IDLArgs.fromBytes(output).getArgs().get(0).getValue(new PojoDeserializer(), LoanOffer.class);	
```

{% endcode %}


# JSON Jackson Serializer and Deserializer

Use [JacksonSerializer](https://github.com/ic4j/ic4j-candid/blob/master/src/main/java/org/ic4j/candid/jackson/JacksonSerializer.java) and [JacksonDeserializer](https://github.com/ic4j/ic4j-candid/blob/master/src/main/java/org/ic4j/candid/jackson/JacksonDeserializer.java) to serialize and deserialize [Java Jackson](https://github.com/FasterXML/jackson) JSON object to and from the Candid payload of type RECORD.&#x20;

A fully functional example using JacksonSerializer and JacksonDeserializer can be found [here](https://github.com/ic4j/samples/tree/master/IC4JJacksonSample).

This example uses Motoko to call the canister [main.mo](https://github.com/ic4j/samples/blob/master/IC4JJacksonSample/src/main.mo). The canister uses 2 complex types, **LoanApplication** and **LoanOffer.**

{% code title="main.mo" %}

```javascript
// Loan Application
public type LoanApplication = {
    id: Nat;
    firstname: Text;
    lastname: Text;
    zipcode: Text;
    ssn: Text;
    amount: Float;
    term: Nat16;
    created: Int;
 };

// Loan Offer
public type LoanOffer = {
    providerid: Principal;
    providername: Text;
    applicationid: Nat;
    apr: Float;
    created: Int;
};
```

{% endcode %}

The canister has 2 methods:  **apply** and **getOffers.**

{% code title="main.mo" %}

```javascript
public shared (msg) func apply(input : LoanApplication) : async LoanOffer { 
       counter += 1;
        Debug.print("Loan Application for user " #Principal.toText(msg.caller));
        
        let offer  : LoanOffer = {
            providerid = Principal.fromActor(this);
            providername = "Loan Provider";
            applicationid = counter;
            apr = 3.14;
            created = Time.now();
        };

        var userOffers :  ?Offers<LoanOffer> = offers.get(msg.caller);

        switch userOffers {
            case (null) { var userOffer : Offers<LoanOffer> = Buffer.Buffer(0); userOffer.add(offer);  offers.put(msg.caller, userOffer)};
            case (?userOffer) { userOffer.add(offer); };
        };
        return offer;
};

public query (msg) func getOffers() : async [LoanOffer] {
        var userOffers :  ?Offers<LoanOffer> = offers.get(msg.caller);

        switch userOffers {
            case (null) { return [] };
            case (?userOffer) { return userOffer.toArray() };
        };
};
```

{% endcode %}

The example uses the file with JSON [LoanApplication payload](https://github.com/ic4j/samples/blob/master/IC4JJacksonSample/src/resources/LoanApplication.json) as an input.&#x20;

{% code title=" LoanApplication.json" %}

```json
{
"id" : 0,
"firstname" : "John",
"lastname" : "Doe",
"zipcode" : "99999",
"ssn" : "111-11-1111",
"amount" : 2000.00,
"term" : 24,
"created" : 0
}
```

{% endcode %}

To be able to properly map JSON names and values to Candid name types declare the [IDLType](/reference/api-reference/using-idlargs#idltype) structure as follows:

{% code title="Main.java" %}

```java
Map<Label,IDLType> applicationRecord = new TreeMap<Label,IDLType>();
applicationRecord.put(Label.createNamedLabel("id"), IDLType.createType(Type.NAT));
applicationRecord.put(Label.createNamedLabel("firstname"), IDLType.createType(Type.TEXT));
applicationRecord.put(Label.createNamedLabel("lastname"), IDLType.createType(Type.TEXT));
applicationRecord.put(Label.createNamedLabel("zipcode"), IDLType.createType(Type.TEXT));
applicationRecord.put(Label.createNamedLabel("ssn"), IDLType.createType(Type.TEXT));		
applicationRecord.put(Label.createNamedLabel("amount"), IDLType.createType(Type.FLOAT64));
applicationRecord.put(Label.createNamedLabel("term"), IDLType.createType(Type.NAT16));
applicationRecord.put(Label.createNamedLabel("created"), IDLType.createType(Type.INT));
		
IDLType idlType =  IDLType.createType(Type.RECORD, applicationRecord);
		
Map<Label,IDLType> offerRecord = new TreeMap<Label,IDLType>();
offerRecord.put(Label.createNamedLabel("providerid"), IDLType.createType(Type.PRINCIPAL));
offerRecord.put(Label.createNamedLabel("providername"), IDLType.createType(Type.TEXT));
offerRecord.put(Label.createNamedLabel("applicationid"), IDLType.createType(Type.NAT));	
offerRecord.put(Label.createNamedLabel("apr"), IDLType.createType(Type.FLOAT64));		
offerRecord.put(Label.createNamedLabel("created"), IDLType.createType(Type.INT));
		
IDLType resultIdlType =  IDLType.createType(Type.RECORD, offerRecord);	
```

{% endcode %}

Next, create IDLValue using the **JacksonSerializer create** method.&#x20;

The Serializer input is the variable type [JsonNode](https://fasterxml.github.io/jackson-databind/javadoc/2.7/com/fasterxml/jackson/databind/JsonNode.html).

{% code title="Main.java" %}

```java
JsonNode jsonValue = readNode(LOAN_APPLICATION_FILE);
		
IDLValue idlValue = IDLValue.create(jsonValue, JacksonSerializer.create(idlType));
List<IDLValue> idlArgs = new ArrayList<IDLValue>();
idlArgs.add(idlValue);

byte[] buf = IDLArgs.create(idlArgs).toBytes();
```

{% endcode %}

Use[ UpdateBuilder](/reference/api-reference/querybuilder-and-updatebuilder#updatebuilder), [QueryBuilder](/reference/api-reference/querybuilder-and-updatebuilder#querybuilder) or[ Raw Methods](/reference/api-reference/using-raw-agent-methods) to call the Canister and deserialize output to [JsonNode](https://fasterxml.github.io/jackson-databind/javadoc/2.7/com/fasterxml/jackson/databind/JsonNode.html).&#x20;

{% code title="Main.java" %}

```java
CompletableFuture<byte[]> response = UpdateBuilder.create(agent,Principal.fromString(icCanister), "apply").arg(buf).callAndWait(Waiter.create(60, 5));
		
byte[] output = response.get();
JsonNode jsonResult = IDLArgs.fromBytes(output).getArgs().get(0)
			.getValue(JacksonDeserializer.create(resultIdlType), JsonNode.class);
```

{% endcode %}


# JSON Gson Serializer and Deserializer

Alternative option to work with JSON in Java is to use [Google Gson](https://github.com/google/gson) open source library.

Use [GsonSerializer](https://github.com/ic4j/ic4j-candid/blob/master/src/main/java/org/ic4j/candid/gson/GsonSerializer.java) and [GsonDeserializer](https://github.com/ic4j/ic4j-candid/blob/master/src/main/java/org/ic4j/candid/gson/GsonDeserializer.java) to serialize and deserialize [Java Gson](https://github.com/google/gson) JSON object to and from the Candid payload of type RECORD.&#x20;

A fully functional example using GsonSerializer and GsonDeserializer can be found [here](https://github.com/ic4j/samples/tree/master/IC4JGsonSample).

This example uses Motoko to call the canister [main.mo](https://github.com/ic4j/samples/blob/master/IC4JGsonSample/src/main.mo). The canister uses 2 complex types, **LoanApplication** and **LoanOffer.**

{% code title="main.mo" %}

```javascript
// Loan Application
public type LoanApplication = {
    id: Nat;
    firstname: Text;
    lastname: Text;
    zipcode: Text;
    ssn: Text;
    amount: Float;
    term: Nat16;
    created: Int;
 };

// Loan Offer
public type LoanOffer = {
    providerid: Principal;
    providername: Text;
    applicationid: Nat;
    apr: Float;
    created: Int;
};
```

{% endcode %}

The canister has 2 methods:  **apply** and **getOffers.**

{% code title="main.mo" %}

```javascript
public shared (msg) func apply(input : LoanApplication) : async LoanOffer { 
       counter += 1;
        Debug.print("Loan Application for user " #Principal.toText(msg.caller));
        
        let offer  : LoanOffer = {
            providerid = Principal.fromActor(this);
            providername = "Loan Provider";
            applicationid = counter;
            apr = 3.14;
            created = Time.now();
        };

        var userOffers :  ?Offers<LoanOffer> = offers.get(msg.caller);

        switch userOffers {
            case (null) { var userOffer : Offers<LoanOffer> = Buffer.Buffer(0); userOffer.add(offer);  offers.put(msg.caller, userOffer)};
            case (?userOffer) { userOffer.add(offer); };
        };
        return offer;
};

public query (msg) func getOffers() : async [LoanOffer] {
        var userOffers :  ?Offers<LoanOffer> = offers.get(msg.caller);

        switch userOffers {
            case (null) { return [] };
            case (?userOffer) { return userOffer.toArray() };
        };
};
```

{% endcode %}

The example uses the file with JSON [LoanApplication payload](https://github.com/ic4j/samples/blob/master/IC4JGsonSample/src/resources/LoanApplication.json) as an input.&#x20;

{% code title=" LoanApplication.json" %}

```json
{
"id" : 0,
"firstname" : "John",
"lastname" : "Doe",
"zipcode" : "99999",
"ssn" : "111-11-1111",
"amount" : 2000.00,
"term" : 24,
"created" : 0
}
```

{% endcode %}

To be able to properly map JSON names and values to Candid name types declare the [IDLType](/reference/api-reference/using-idlargs#idltype) structure as follows:

{% code title="Main.java" %}

```java
Map<Label,IDLType> applicationRecord = new TreeMap<Label,IDLType>();
applicationRecord.put(Label.createNamedLabel("id"), IDLType.createType(Type.NAT));
applicationRecord.put(Label.createNamedLabel("firstname"), IDLType.createType(Type.TEXT));
applicationRecord.put(Label.createNamedLabel("lastname"), IDLType.createType(Type.TEXT));
applicationRecord.put(Label.createNamedLabel("zipcode"), IDLType.createType(Type.TEXT));
applicationRecord.put(Label.createNamedLabel("ssn"), IDLType.createType(Type.TEXT));		
applicationRecord.put(Label.createNamedLabel("amount"), IDLType.createType(Type.FLOAT64));
applicationRecord.put(Label.createNamedLabel("term"), IDLType.createType(Type.NAT16));
applicationRecord.put(Label.createNamedLabel("created"), IDLType.createType(Type.INT));
		
IDLType idlType =  IDLType.createType(Type.RECORD, applicationRecord);
		
Map<Label,IDLType> offerRecord = new TreeMap<Label,IDLType>();
offerRecord.put(Label.createNamedLabel("providerid"), IDLType.createType(Type.PRINCIPAL));
offerRecord.put(Label.createNamedLabel("providername"), IDLType.createType(Type.TEXT));
offerRecord.put(Label.createNamedLabel("applicationid"), IDLType.createType(Type.NAT));	
offerRecord.put(Label.createNamedLabel("apr"), IDLType.createType(Type.FLOAT64));		
offerRecord.put(Label.createNamedLabel("created"), IDLType.createType(Type.INT));
		
IDLType resultIdlType =  IDLType.createType(Type.RECORD, offerRecord);	
```

{% endcode %}

Next, create IDLValue using the **GsonSerializer create** method.&#x20;

The Serializer input is the variable type [JsonElemen](https://www.javadoc.io/doc/com.google.code.gson/gson/2.8.5/com/google/gson/JsonElement.html)t.

{% code title="Main.java" %}

```java
JsonElement jsonValue = readNode(LOAN_APPLICATION_FILE)		
IDLValue idlValue = IDLValue.create(jsonValue, GsonSerializer.create(idlType));
		
List<IDLValue> idlArgs = new ArrayList<IDLValue>();		
idlArgs.add(idlValue);
byte[] buf = IDLArgs.create(idlArgs).toBytes();
```

{% endcode %}

Use[ UpdateBuilder](/reference/api-reference/querybuilder-and-updatebuilder#updatebuilder), [QueryBuilder](/reference/api-reference/querybuilder-and-updatebuilder#querybuilder) or[ Raw Methods](/reference/api-reference/using-raw-agent-methods) to call the Canister and deserialize output to [JsonElement](https://www.javadoc.io/doc/com.google.code.gson/gson/2.8.5/com/google/gson/JsonElement.html).&#x20;

{% code title="Main.java" %}

```java
CompletableFuture<byte[]> response = UpdateBuilder.create(agent,Principal.fromString(icCanister), "apply").arg(buf).callAndWait(Waiter.create(60, 5));
		
byte[] output = response.get();
JsonElement jsonResult = IDLArgs.fromBytes(output).getArgs().get(0)
		.getValue(GsonDeserializer.create(resultIdlType), JsonElement.class);

```

{% endcode %}


# XML DOM Serializer and Deserializer

Use [DOMSerializer](https://github.com/ic4j/ic4j-candid/blob/master/src/main/java/org/ic4j/candid/dom/DOMSerializer.java) and [DOMDeserializer](https://github.com/ic4j/ic4j-candid/blob/master/src/main/java/org/ic4j/candid/dom/DOMDeserializer.java) to serialize and deserialize [Java XML DOM](https://docs.oracle.com/javase/8/docs/api/org/w3c/dom/package-summary.html) object to and from the Candid payload of type RECORD.&#x20;

A fully functional example using DOMSerializer and DOMDeserializer can be found [here](https://github.com/ic4j/samples/tree/master/IC4JXMLSample).

This example uses Motoko to call the canister [main.mo](https://github.com/ic4j/samples/blob/master/IC4JXMLSample/src/main.mo). The canister uses 2 complex types, **LoanApplication** and **LoanOffer.**

{% code title="main.mo" %}

```javascript
// Loan Application
public type LoanApplication = {
    id: Nat;
    firstname: Text;
    lastname: Text;
    zipcode: Text;
    ssn: Text;
    amount: Float;
    term: Nat16;
    created: Int;
 };

// Loan Offer
public type LoanOffer = {
    providerid: Principal;
    providername: Text;
    applicationid: Nat;
    apr: Float;
    created: Int;
};
```

{% endcode %}

The canister has 2 methods:  **apply** and **getOffers.**

{% code title="main.mo" %}

```javascript
public shared (msg) func apply(input : LoanApplication) : async LoanOffer { 
       counter += 1;
        Debug.print("Loan Application for user " #Principal.toText(msg.caller));
        
        let offer  : LoanOffer = {
            providerid = Principal.fromActor(this);
            providername = "Loan Provider";
            applicationid = counter;
            apr = 3.14;
            created = Time.now();
        };

        var userOffers :  ?Offers<LoanOffer> = offers.get(msg.caller);

        switch userOffers {
            case (null) { var userOffer : Offers<LoanOffer> = Buffer.Buffer(0); userOffer.add(offer);  offers.put(msg.caller, userOffer)};
            case (?userOffer) { userOffer.add(offer); };
        };
        return offer;
};

public query (msg) func getOffers() : async [LoanOffer] {
        var userOffers :  ?Offers<LoanOffer> = offers.get(msg.caller);

        switch userOffers {
            case (null) { return [] };
            case (?userOffer) { return userOffer.toArray() };
        };
};
```

{% endcode %}

The example uses the file with [XML LoanApplication](https://github.com/ic4j/samples/blob/master/IC4JXMLSample/src/resources/LoanApplication.xml) payload as an input.&#x20;

{% code title=" LoanApplication.xml" %}

```xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<data xmlns="http://ic4j.org/samples" xmlns:candid="http://ic4j.org/candid" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" candid:type="RECORD">
<amount candid:name="amount" candid:type="FLOAT64" xsi:type="xsd:double">20000.00</amount>
<term candid:name="term" candid:type="NAT16" xsi:type="xsd:unsignedShort">24</term>
<created candid:name="created" candid:type="INT" xsi:type="xsd:integer">0</created>
<id candid:name="id" candid:type="NAT" xsi:type="xsd:positiveInteger">0</id>
<firstname candid:name="firstname" candid:type="TEXT" xsi:type="xsd:string">John</firstname>
<lastname candid:name="lastname" candid:type="TEXT" xsi:type="xsd:string">Doe</lastname>
<zipcode candid:name="zipcode" candid:type="TEXT" xsi:type="xsd:string">99999</zipcode>
<ssn candid:name="ssn" candid:type="TEXT" xsi:type="xsd:string">111-11-1111</ssn>
</data>

```

{% endcode %}

Next, create IDLValue using the **DOMSerializer create** method.&#x20;

The Serializer input is the variable type DOM [Element](https://docs.oracle.com/javase/8/docs/api/org/w3c/dom/Element.html).

{% code title="Main.java" %}

```java
Element xmlValue = readNode(LOAN_APPLICATION_FILE);
		
IDLValue idlValue = IDLValue.create(xmlValue, DOMSerializer.create());
List<IDLValue> idlArgs = new ArrayList<IDLValue>();
idlArgs.add(idlValue);

byte[] buf = IDLArgs.create(idlArgs).toBytes();
```

{% endcode %}

To be able to properly map names and values to Candid name types for DOMDeserializer, declare the [IDLType](/reference/api-reference/using-idlargs#idltype) structure as follows:

{% code title="Main.java" %}

```java
Map<Label,IDLType> offerRecord = new TreeMap<Label,IDLType>();
offerRecord.put(Label.createNamedLabel("providerid"), IDLType.createType(Type.PRINCIPAL));
offerRecord.put(Label.createNamedLabel("providername"), IDLType.createType(Type.TEXT));
offerRecord.put(Label.createNamedLabel("applicationid"), IDLType.createType(Type.NAT));	
offerRecord.put(Label.createNamedLabel("apr"), IDLType.createType(Type.FLOAT64));		
offerRecord.put(Label.createNamedLabel("created"), IDLType.createType(Type.INT));
		
IDLType resultIdlType =  IDLType.createType(Type.RECORD, offerRecord);	
```

{% endcode %}

Use[ UpdateBuilder](/reference/api-reference/querybuilder-and-updatebuilder#updatebuilder), [QueryBuilder](/reference/api-reference/querybuilder-and-updatebuilder#querybuilder) or[ Raw Methods](/reference/api-reference/using-raw-agent-methods) to call the Canister and deserialize output to DOM [Element](https://docs.oracle.com/javase/8/docs/api/org/w3c/dom/Element.html).  Function **rootElement** is used to define root element of the XML structure. To set [Candid XML Attributes](#undefined) in XML output use **setAttributes** function with **true** value.

{% code title="Main.java" %}

```java
CompletableFuture<byte[]> response = UpdateBuilder.create(agent,Principal.fromString(icCanister), "apply").arg(buf).callAndWait(Waiter.create(60, 5));
		
byte[] output = response.get();
Element  xmlResult = IDLArgs.fromBytes(output).getArgs().get(0)
		.getValue(DOMDeserializer.create(resultIdlType)
		.rootElement("http://ic4j.org/samples", "data").setAttributes(true), Element.class);
```

{% endcode %}

By default, DOMDeserializer generates **qualified** XML document with namespaces. To generate **unqualified** XML document use DOMDeserializer function **setQualified** with **false** value.

## XSI Types

DOMSerializer can use XML XSI attribute to convert XML value to specific primitive Candid type.&#x20;

```xml
<data xmlns="http://ic4j.org/samples" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<amount xsi:type="xsd:double">20000.00</amount>
<term xsi:type="xsd:unsignedShort">24</term>
</data>
```

XSI XML namespace is **<http://www.w3.org/2001/XMLSchema-instance>**. Type is defined as XML Schema type <http://www.w3.org/2001/XMLSchema>.

Here is mapping table between Candid and XML Schema.

| Candid    | XML Schema     |
| --------- | -------------- |
| bool      | boolean        |
| int       | integer        |
| int8      | byte           |
| int16     | short          |
| int32     | int            |
| int64     | long           |
| nat       | posiiveInteger |
| nat8      | unsignedByte   |
| nat16     | unsignedShort  |
| nat32     | unsignedInt    |
| nat64     | unsignedLong   |
| float32   | float          |
| float64   | double         |
| text      | string         |
| principal | ID             |

## Using Candid XML Attributes

The developer can also use Candid XML attributes **name** and **type** to define Candid name and type. If XML document is qualified then it requires candid namespace definition **<http://ic4j.org/candid>.**

```xml
<data xmlns="http://ic4j.org/samples" xmlns:candid="http://ic4j.org/candid" candid:type="RECORD">
<amount candid:name="amount" candid:type="FLOAT64">20000.00</amount>
<term candid:name="term" candid:type="NAT16">24</term>
</data>
```

## Handling XML Arrays

By default, DOMSerializer and DOMDeserializer will assume that name of array item is **item**. To modify this name use function **arrayItem** in DOMSerializer and DOMDeserializer.


# XML JAXB Serializer and Deserializer

Use [JAXBSerializer](https://github.com/ic4j/ic4j-candid/blob/master/src/main/java/org/ic4j/candid/jaxb/JAXBSerializer.java) and [JAXBDeserializer](https://github.com/ic4j/ic4j-candid/blob/master/src/main/java/org/ic4j/candid/jaxb/JAXBDeserializer.java) to serialize and deserialize [Java XML JAXB ](https://docs.oracle.com/javase/tutorial/jaxb/intro/index.html)object to and from the Candid payload of type RECORD.&#x20;

Java Architecture for XML Binding (JAXB) is a standard that defines an API for reading and writing Java objects to and from XML documents. It applies a lot of defaults, thus making reading and writing of XML via Java relatively easy.

With Java releases lower than Java 11, JAXB was part of the JVM and you could use it directly without defining additional libaries.

As of Java 11, JAXB is not part of the JRE anymore and you need to configure the relevant libraries via your dependency management system, for example Maven or Gradle.&#x20;

A fully functional example using JAXBSerializer and JAXBDeserializer can be found [here](https://github.com/ic4j/samples/tree/master/IC4JJAXBSample).

This example uses Motoko to call the canister [main.mo](https://github.com/ic4j/samples/blob/master/IC4JJAXBSample/src/main.mo). The canister uses 2 complex types, **LoanApplication** and **LoanOffer.**

{% code title="main.mo" %}

```javascript
  // Loan Application
public type LoanApplication = {
    id: Int;
    firstname: Text;
    lastname: Text;
    zipcode: Text;
    ssn: Text;
    amount: Float;
    term: Int16;
    created: Int;
 };

 // Loan Offer
public type LoanOffer = {
    providerid: Text;
    providername: Text;
    applicationid: Int;
    apr: Float;
    created: Int;
};
```

{% endcode %}

The canister has one method:  **apply.**

{% code title="main.mo" %}

```javascript
public shared (msg) func apply(input : LoanApplication) : async LoanOffer {

    Debug.print("Loan Application for user " #Principal.toText(msg.caller));
        
    let offer  : LoanOffer = {
            providerid = Principal.toText(Principal.fromActor(this));
            providername = "Loan Provider";
            applicationid = 1;
            apr = 3.14;
            created = Time.now();
    };

    return offer;
};
```

{% endcode %}

To call this canister the annotated proxy Java interface [LoanProxy.java](https://github.com/ic4j/samples/blob/master/IC4JJAXBSample/src/main/org/ic4j/samples/jaxb/LoanProxy.java) and [ProxyBuilder](/reference/api-reference/proxybuilder) will be used.&#x20;

{% code title="LoanProxy.java" %}

```java
public interface LoanProxy {	
	@UPDATE
	@Name("apply")
	@Deserializer(JAXBDeserializer.class)
	@Waiter(timeout = 30)
	public CompletableFuture<LoanOffer> apply(@Serializer(JAXBSerializer.class) @Argument(Type.RECORD) LoanApplication loanApplication);	
}
```

{% endcode %}

LoanApplication and LoanOffer Java classes with the JAXB annotation are defined in [LoanApplication.java](https://github.com/ic4j/samples/blob/master/IC4JJAXBSample/src/main/org/ic4j/samples/jaxb/LoanApplication.java) and [LoanOffer.java](https://github.com/ic4j/samples/blob/master/IC4JJAXBSample/src/main/org/ic4j/samples/jaxb/LoanOffer.java).

{% code title="LoanApplication.java" %}

```java
@XmlRootElement(name = "data", namespace="http://ic4j.org/samples")
public class LoanApplication{
	@XmlElement(name="id", namespace="http://ic4j.org/samples", required=true)
    public BigInteger id;
	@XmlElement(name="amount", namespace="http://ic4j.org/samples", required=true)
	public Double amount;
	@XmlElement(name="term", namespace="http://ic4j.org/samples", required=true)   
    public Short term;
	@XmlElement(name="firstname", namespace="http://ic4j.org/samples", required=true)
    public String firstName;
	@XmlElement(name="lastname", namespace="http://ic4j.org/samples", required=true)
    public String lastName;
	@XmlElement(name="ssn", namespace="http://ic4j.org/samples", required=true)
    public String ssn;
	@XmlElement(name="zipcode", namespace="http://ic4j.org/samples", required=true)
    public String zipcode;
	@XmlElement(name="created", namespace="http://ic4j.org/samples", required=true)
    public BigInteger created;
}
```

{% endcode %}

{% code title="LoanOffer.java" %}

```java
@XmlRootElement(name = "data", namespace="http://ic4j.org/samples")
public class LoanOffer{
	@XmlElement(name="providerid", namespace="http://ic4j.org/samples", required=true)
    public String providerId;	
	@XmlElement(name="providername", namespace="http://ic4j.org/samples", required=true)
    public String providerName;    
	@XmlElement(name="userid", namespace="http://ic4j.org/samples", required=true)
    public Principal userId;
	@XmlElement(name="applicationid", namespace="http://ic4j.org/samples", required=true)
    public Integer applicationId;
	@XmlElement(name="apr", namespace="http://ic4j.org/samples", required=true)
    public Double apr;
	@XmlElement(name="created", namespace="http://ic4j.org/samples", required=true)
    public Long created;
}
```

{% endcode %}

The example uses the file with [XML LoanApplication payload ](https://github.com/ic4j/samples/blob/master/IC4JJAXBSample/src/resources/LoanApplication.xml)as an input.&#x20;

{% code title=" LoanApplication.xml" %}

```xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<data xmlns="http://ic4j.org/samples" xmlns:candid="http://ic4j.org/candid" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" candid:type="RECORD">
<amount candid:name="amount" candid:type="FLOAT64" xsi:type="xsd:double">20000.00</amount>
<term candid:name="term" candid:type="NAT16" xsi:type="xsd:unsignedShort">24</term>
<created candid:name="created" candid:type="INT" xsi:type="xsd:integer">0</created>
<id candid:name="id" candid:type="NAT" xsi:type="xsd:positiveInteger">0</id>
<firstname candid:name="firstname" candid:type="TEXT" xsi:type="xsd:string">John</firstname>
<lastname candid:name="lastname" candid:type="TEXT" xsi:type="xsd:string">Doe</lastname>
<zipcode candid:name="zipcode" candid:type="TEXT" xsi:type="xsd:string">99999</zipcode>
<ssn candid:name="ssn" candid:type="TEXT" xsi:type="xsd:string">111-11-1111</ssn>
</data>

```

{% endcode %}

Next, create LoanApplication object using the **JAXB Unmarshaller**.&#x20;

{% code title="Main.java" %}

```java
JAXBContext context = JAXBContext.newInstance(LoanApplication.class);
LoanApplication loanApplication =  (LoanApplication) context.createUnmarshaller()		
	      .unmarshal(Main.class.getClassLoader().getResourceAsStream(LOAN_APPLICATION_FILE));
```

{% endcode %}

By default, JAXB**Serializer** and JAXB**Deserializer** will use [Java to Candid type mapping](/reference/api-reference/supported-types) and use the Java member variable name as the name of the Candid RECORD field.&#x20;

Use JAXB annotations [@XmlElement](https://docs.oracle.com/javase/8/docs/api/javax/xml/bind/annotation/XmlElement.html), [@XmlAttribute](https://docs.oracle.com/javase/8/docs/api/javax/xml/bind/annotation/XmlAttribute.html) or [@XmlEnumValue](https://docs.oracle.com/javase/8/docs/api/javax/xml/bind/annotation/XmlEnumValue.html) to override the default  name.

To skip serialization and deserialization of certain member variables, use the[ @XmlTransient](https://docs.oracle.com/javase/8/docs/api/javax/xml/bind/annotation/XmlTransient.html) annotation.

[ProxyBuilder](/reference/api-reference/proxybuilder) will  use JAXBSerializer and JAXBDeserializer defined in Java Candid [Serializer](https://github.com/ic4j/ic4j-candid/blob/master/src/main/java/org/ic4j/candid/annotations/Serializer.java) and [Deserializer](https://github.com/ic4j/ic4j-candid/blob/master/src/main/java/org/ic4j/candid/annotations/Deserializer.java) annotations to convert Candid RECORD to a Java JAXB object.

{% code title="Main.java" %}

```java
LoanOffer loanOffer = loanProxy.apply(loanApplication).get();
```

{% endcode %}

To use [Raw methods](/reference/api-reference/using-raw-agent-methods) or [QueryBuilder](/reference/api-reference/querybuilder-and-updatebuilder#querybuilder) and [UpdateBuilder](/reference/api-reference/querybuilder-and-updatebuilder#updatebuilder) use JAXBSerializer and JAXBDeserializer directly in the Java code.

```java
IDLValue idlValue = IDLValue.create(loanApplication, new JAXBSerializer());
List<IDLValue> args = new ArrayList<IDLValue>();
args.add(idlValue);
IDLArgs idlArgs = IDLArgs.create(args);

byte[] payload = idlArgs.toBytes();

CompletableFuture<byte[]> response = UpdateBuilder
	.create(agent, Principal.fromString(canisterid), "apply")
	.expireAfter(Duration.ofMinutes(3))
	.arg(payload)
	.callAndWait(Waiter.create(60, 5));
	
byte[] output = queryResponse.get();

LoanOffer loanOffer = IDLArgs.fromBytes(output).getArgs().get(0).getValue(new JAXBDeserializer(), LoanOffer.class);	
```


# JDBC Serializer

Use [JDBCSerializer](https://github.com/ic4j/ic4j-candid/blob/master/src/main/java/org/ic4j/candid/jdbc/JDBCSerializer.java) to serialize Java [JDBC ResultSet](https://docs.oracle.com/javase/8/docs/api/java/sql/ResultSet.html) object to the Candid payload of type RECORD.&#x20;

A fully functional example using JDBCSerializer  can be found [here](https://github.com/ic4j/samples/tree/master/IC4JJDBCSample).

This example uses Motoko to call the canister [main.mo](https://github.com/ic4j/samples/blob/master/IC4JJDBCSample/src/main.mo). The canister uses  complex type  **CreditCheck.**

{% code title="main.mo" %}

```javascript
  // Credit Check
  public type Credit = {
    ssn: Text;   
    rating: Int32;
  };
```

{% endcode %}

The canister has 1 method:  **apply** and **setCredit.**

{% code title="main.mo" %}

```javascript
    public shared (msg) func setCredit(input : Credit){
        Debug.print("Credit Check for ssn " #input.ssn);
    };
```

{% endcode %}

The example uses the data from embedded [Apache Derby](https://db.apache.org/derby/) SQL database as an input. Database table is reinitialized every time the sample runs.

{% code title="Main.java" %}

```java
Statement statement = connection.createStatement();
String sql = "CREATE TABLE data (ssn VARCHAR(11) PRIMARY KEY,rating INT)";
statement.execute(sql);
sql = "INSERT INTO data VALUES ('111-11-1111',550)";
statement.execute(sql);
sql = "INSERT INTO data VALUES ('222-22-2222',650)";
statement.execute(sql);
sql = "INSERT INTO data VALUES ('333-33-3333',750)";
statement.execute(sql);
```

{% endcode %}

Execute [JDBC PreparedStatement](https://docs.oracle.com/javase/8/docs/api/java/sql/PreparedStatement.html) to get ResultSet data from the database.

{% code title="Main.java" %}

```java
PreparedStatement statement = connection.prepareStatement("SELECT ssn, rating FROM data WHERE ssn = ?");

String ssn = "222-22-2222";
statement.setString(1, ssn);
ResultSet result = statement.executeQuery();	
```

{% endcode %}

The Serializer input is the variable of type [ResultSet](https://docs.oracle.com/javase/8/docs/api/java/sql/ResultSet.html). To serialize individual row from ResultSet to Candid RECORD use function **array** with **false** value. Otherwise the result will be Candid VEC type, wrapping Candid RECORD items.

{% code title="Main.java" %}

```java
IDLValue idlValue = IDLValue.create(result, JDBCSerializer.create().array(false));
List<IDLValue> idlArgs = new ArrayList<IDLValue>();
idlArgs.add(idlValue);

byte[] buf = IDLArgs.create(idlArgs).toBytes();
```

{% endcode %}

Use[ UpdateBuilder](/reference/api-reference/querybuilder-and-updatebuilder#updatebuilder), [QueryBuilder](/reference/api-reference/querybuilder-and-updatebuilder#querybuilder) or[ Raw Methods](/reference/api-reference/using-raw-agent-methods) to call the Canister.&#x20;

{% code title="Main.java" %}

```java
CompletableFuture<byte[]> response = UpdateBuilder.create(agent, Principal.fromString(icCanister), "setCredit").arg(buf)
    .callAndWait(Waiter.create(60, 5));

byte[] output = response.get();
```

{% endcode %}


# Android Development

IC4J Agent library can be also used for development of native Android application written in Java or Kotlin. Use [Android Studio](https://developer.android.com/studio) to start a new Android application or add support for the Internet Computer to your existing application.

To add required IC4J libraries to your Android project open **gradle.build** file and add dependencies:

```
    implementation 'commons-codec:commons-codec:1.17.0'
    implementation 'org.ic4j:ic4j-candid:0.8.0'
    implementation('org.ic4j:ic4j-agent:0.8.0') {
        exclude group: 'org.apache.httpcomponents.client5', module: 'httpclient5'
    }
    implementation 'org.slf4j:slf4j-api:2.0.13'
```

Android application preferably uses [OkHttp HTTP](/reference/api-reference/replicatransport#okhttp-client-transport-implementation) client so Apache HTTP 5 library can be excluded.

To be able to connect to the Internet Computer Canister set **uses-permission** in project AndroidManifest.xml descriptor.

```xml
<uses-permission android:name="android.permission.INTERNET"/>
```

## Use IC4J with Kotlin

[AndroidHelloWord](https://github.com/ic4j/samples/tree/master/AndroidHelloWorld) sample application demonstrates use or [QueryBuilder](/reference/api-reference/querybuilder-and-updatebuilder#querybuilder) and [UpdateBuilder](/reference/api-reference/querybuilder-and-updatebuilder#updatebuilder) in Kotlin Android project. Project properties **ic.location** and **ic.canister** are stored in [strings.xml](https://github.com/ic4j/samples/blob/master/AndroidHelloWorld/app/src/main/res/values/strings.xml) file.

[MainActivity.kt](https://github.com/ic4j/samples/blob/master/AndroidHelloWorld/app/src/main/java/org/ic4j/samples/android/helloworld/MainActivity.kt) has a simple code for QUERY and UPDATE invocation of the Canister code [main.mo](https://github.com/ic4j/samples/blob/master/AndroidHelloWorld/main.mo).

{% code title="main.mo" %}

```javascript
actor {
    stable var name = "Me";

    public func greet(value : Text) : async Text {
        name := value;
        return "Hello, " # name # "!";
    };

    public shared query func peek() : async Text {
        return name;
    };
};
```

{% endcode %}

Using [QueryBuilder](/reference/api-reference/querybuilder-and-updatebuilder#querybuilder) in Kotlin.

{% code title="MainActivity.kt" %}

```kotlin
val url: String = getString(R.string.url)
val canister: String = getString(R.string.canister)

val identity: Identity = AnonymousIdentity()
val transport: ReplicaTransport =
                ReplicaOkHttpTransport.create(url)

val agent: Agent = AgentBuilder().identity(identity).transport(transport).build()
val buf = IDLArgs.create(ArrayList<IDLValue>()).toBytes()
val principal = Principal.fromString(canister);

val response = QueryBuilder.create(
                        agent,
                        principal,
                        "peek"
           ).arg(buf).call()

val output = response.get()
val outArgs = IDLArgs.fromBytes(output)
name = outArgs.args[0].getValue<String>()
```

{% endcode %}

Using [UpdateBuilder](/reference/api-reference/querybuilder-and-updatebuilder#updatebuilder) in Kotlin.

{% code title="MainActivity.kt" %}

```kotlin
val url : String = getString(R.string.url)
val canister : String = getString(R.string.canister)

val identity : Identity = AnonymousIdentity()
val transport: ReplicaTransport =
                ReplicaOkHttpTransport.create(url)
val agent: Agent = AgentBuilder().identity(identity).transport(transport).build()

val arg : IDLValue = IDLValue.create(message)
var args : ArrayList<IDLValue> = ArrayList<IDLValue>()
args.add(arg)
val buf = IDLArgs.create(args).toBytes()

val response = UpdateBuilder.create(
                        agent,
                        Principal.fromString(canister),
                        "greet"
            ).arg(buf).callAndWait(Waiter.create(60, 5))

val output = response.get()
val outArgs = IDLArgs.fromBytes(output)
val outputMessage = outArgs.args[0].getValue<String>()
```

{% endcode %}


