Error when executing Camel marshall to CSV file - apache-camel

I'm getting an error trying to run this camel route:
<route>
<from id="_from1" uri="timer:foo?repeatCount=1"/>
<to id="_to3" uri="sql:select nro_servicio, documentodesconexionsap FROM servicio_cab;?dataSource=dataSource"/>
<to id="_to2" uri="bean:com.enelint.pangeaent.GlobalDataController?method=processGlobalData(Exchange)"/>
<marshal id="_marshal1">
<csv/>
</marshal>
<to id="_to1" uri="file:/fs/out?fileName=out.csv"/>
</route>
The stack trace is: Error occurred while running main from: org.apache.camel.test.blueprint.Main.
If I change the marshal to string it creates the output file but obviously with the content not formatted as comma separated.
I'm using Camel version 2.17.
Any help will be appreciated.
UPDATE:
Here is my POJO class:
package com.enelint.pangeaenelint;
import java.util.Date;
import org.apache.camel.dataformat.bindy.annotation.CsvRecord;
import org.apache.camel.dataformat.bindy.annotation.DataField;
#CsvRecord(separator="\\;")
public class ServicioCab {
#DataField(pos=1, required=false)
String documentodesconexionsap;
#DataField(pos=2, required=false)
String nro_cuenta_contrato;
#DataField(pos=3, required=false)
String status;
#DataField(pos=4, required=true)
String motivo_accion;
#DataField(pos=5, required=false, pattern="dd.MM.yyyy")
String fecha_corte_repo;
#DataField(pos=6, required=false)
String hora_corte_repo;
#DataField(pos=7, required=false)
String reemite;
#DataField(pos=8, required=false)
String dias_reemision;
#DataField(pos=9, required=false)
String enviado_sap;
public String getDocumentodesconexionsap() {
return documentodesconexionsap;
}
public void setDocumentodesconexionsap(String documentodesconexionsap) {
this.documentodesconexionsap = documentodesconexionsap;
}
public String getNro_cuenta_contrato() {
return nro_cuenta_contrato;
}
public void setNro_cuenta_contrato(String nro_cuenta_contrato) {
this.nro_cuenta_contrato = nro_cuenta_contrato;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getMotivo_accion() {
return motivo_accion;
}
public void setMotivo_accion(String motivo_accion) {
this.motivo_accion = motivo_accion;
}
public String getFecha_corte_repo() {
return fecha_corte_repo;
}
public void setFecha_corte_repo(String fecha_corte_repo) {
this.fecha_corte_repo = fecha_corte_repo;
}
public String getHora_corte_repo() {
return hora_corte_repo;
}
public void setHora_corte_repo(String hora_corte_repo) {
this.hora_corte_repo = hora_corte_repo;
}
public String getReemite() {
return reemite;
}
public void setReemite(String reemite) {
this.reemite = reemite;
}
public String getDias_reemision() {
return dias_reemision;
}
public void setDias_reemision(String dias_reemision) {
this.dias_reemision = dias_reemision;
}
public String getEnviado_sap() {
return enviado_sap;
}
public void setEnviado_sap(String enviado_sap) {
this.enviado_sap = enviado_sap;
}
}

Related

Canot invok "org.openqa.selenium.WebDriver.findElement(org.openqa.selenium.By)" because "this.driver" is null at pageObject.LandingPage.searchItem

below landingpage.java code and LandingPageStepDefination.java
where to make changes so that NullPointerException issue will resolve
.................Landingpage.java.............
public class **LandingPage** {
public WebDriver driver;
By search=By.xpath("//input[#placeholder='Search for Vegetables and Fruits']");
By ProductName=By.cssSelector("h4.product-name");
By topDeals=By.xpath("//a[normalize-space()='Top Deals']");
public LandingPage(WebDriver driver)
{
this.driver=driver;
}
public void searchItem(String name)
{
driver.findElement(search).sendKeys(name);
}
public String getProductName()
{
return driver.findElement(ProductName).getText();
}
public void SelectTopDealsPage()
{
driver.findElement(topDeals).click();
}
}
...................landingpagestepDefination.java
public class LandingPageStepDefination {
public WebDriver driver;
public String landingproductName;
public String offerpageproductname;
pageObjectManager pageObjectManager;
// setups setups1;
setups setups;
LandingPage LandingPageLandingPage;
public LandingPageStepDefination(setups setups) {
this.setups = setups;
}
#Given("user in greencart landing page")
public void user_in_greencart_landing_page() {
}
#When("user search with shortname {string} and extrach actual name of product")
public void user_search_with_shortname_and_extrach_actual_name_of_product(String Shrotname)
throws InterruptedException {
LandingPage LandingPage = setups.pageObjectManager.getMeLandingPage();
LandingPage.searchItem(Shrotname);
Thread.sleep(5000);
setups.landingproductName = LandingPage.getProductName().split("-")[0].trim();
System.out.println(landingproductName);
}
}

apache flink avro FileSink is struck at in-progress state for long time

I have below avro schema User.avsc
{
"type": "record",
"namespace": "com.myorg",
"name": "User",
"fields": [
{
"name": "id",
"type": "long"
},
{
"name": "name",
"type": "string"
}
]
}
The below java User.java class is generated from above User.avsc using avro-maven-plugin.
package com.myorg;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.nio.ByteBuffer;
import org.apache.avro.AvroRuntimeException;
import org.apache.avro.Schema;
import org.apache.avro.Schema.Parser;
import org.apache.avro.data.RecordBuilder;
import org.apache.avro.io.DatumReader;
import org.apache.avro.io.DatumWriter;
import org.apache.avro.message.BinaryMessageDecoder;
import org.apache.avro.message.BinaryMessageEncoder;
import org.apache.avro.message.SchemaStore;
import org.apache.avro.specific.AvroGenerated;
import org.apache.avro.specific.SpecificData;
import org.apache.avro.specific.SpecificRecord;
import org.apache.avro.specific.SpecificRecordBase;
import org.apache.avro.specific.SpecificRecordBuilderBase;
#AvroGenerated
public class User extends SpecificRecordBase implements SpecificRecord {
private static final long serialVersionUID = 8699049231783654635L;
public static final Schema SCHEMA$ = (new Parser()).parse("{\"type\":\"record\",\"name\":\"User\",\"namespace\":\"com.myorg\",\"fields\":[{\"name\":\"id\",\"type\":\"long\"},{\"name\":\"name\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}}]}");
private static SpecificData MODEL$ = new SpecificData();
private static final BinaryMessageEncoder<User> ENCODER;
private static final BinaryMessageDecoder<User> DECODER;
/** #deprecated */
#Deprecated
public long id;
/** #deprecated */
#Deprecated
public String name;
private static final DatumWriter<User> WRITER$;
private static final DatumReader<User> READER$;
public static Schema getClassSchema() {
return SCHEMA$;
}
public static BinaryMessageDecoder<User> getDecoder() {
return DECODER;
}
public static BinaryMessageDecoder<User> createDecoder(SchemaStore resolver) {
return new BinaryMessageDecoder(MODEL$, SCHEMA$, resolver);
}
public ByteBuffer toByteBuffer() throws IOException {
return ENCODER.encode(this);
}
public static User fromByteBuffer(ByteBuffer b) throws IOException {
return (User)DECODER.decode(b);
}
public User() {
}
public User(Long id, String name) {
this.id = id;
this.name = name;
}
public Schema getSchema() {
return SCHEMA$;
}
public Object get(int field$) {
switch(field$) {
case 0:
return this.id;
case 1:
return this.name;
default:
throw new AvroRuntimeException("Bad index");
}
}
public void put(int field$, Object value$) {
switch(field$) {
case 0:
this.id = (Long)value$;
break;
case 1:
this.name = (String)value$;
break;
default:
throw new AvroRuntimeException("Bad index");
}
}
public Long getId() {
return this.id;
}
public void setId(Long value) {
this.id = value;
}
public String getName() {
return this.name;
}
public void setName(String value) {
this.name = value;
}
public void writeExternal(ObjectOutput out) throws IOException {
WRITER$.write(this, SpecificData.getEncoder(out));
}
public void readExternal(ObjectInput in) throws IOException {
READER$.read(this, SpecificData.getDecoder(in));
}
static {
ENCODER = new BinaryMessageEncoder(MODEL$, SCHEMA$);
DECODER = new BinaryMessageDecoder(MODEL$, SCHEMA$);
WRITER$ = MODEL$.createDatumWriter(SCHEMA$);
READER$ = MODEL$.createDatumReader(SCHEMA$);
}
}
I want to write an instance of User SpecificRecord into File using apache flink`s FileSink.
Below is the program that I wrote -
import org.apache.flink.connector.file.sink.FileSink;
import org.apache.flink.core.fs.Path;
import org.apache.flink.formats.avro.AvroWriters;
import org.apache.flink.streaming.api.CheckpointingMode;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import com.myorg.User;
import org.apache.flink.streaming.api.functions.sink.filesystem.OutputFileConfig;
import org.apache.flink.streaming.api.functions.sink.filesystem.bucketassigners.DateTimeBucketAssigner;
import org.apache.flink.streaming.api.functions.sink.filesystem.rollingpolicies.OnCheckpointRollingPolicy;
import java.util.Arrays;
public class AvroFileSinkApp {
private static final String OUTPUT_PATH = "./il/";
public static void main(String[] args) throws Exception {
final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment().enableCheckpointing(5000);
env.getCheckpointConfig().setCheckpointingMode(CheckpointingMode.EXACTLY_ONCE);
env.setParallelism(4);
OutputFileConfig config = OutputFileConfig
.builder()
.withPartPrefix("il")
.withPartSuffix(".avro")
.build();
DataStream<User> source = env.fromCollection(Arrays.asList(getUser(), getUser(), getUser(), getUser(), getUser(), getUser()));
source.sinkTo(FileSink.forBulkFormat(new Path(OUTPUT_PATH), AvroWriters.forSpecificRecord(User.class)).withBucketCheckInterval(5000).withRollingPolicy(OnCheckpointRollingPolicy.build())
.withOutputFileConfig(config).withBucketAssigner(new DateTimeBucketAssigner<>("yyyy/MM/dd/HH")).build());
env.execute("FileSinkProgram");
Thread.sleep(300000);
}
public static User getUser() {
User u = new User();
u.setId(1L);
u.setName("raj");
return u;
}
}
I wrote this program using this and this as reference. The project is on github here.
When I run the program, the in progress files are getting created but not checkpointing and committing the temp files. I've added Thread.sleep(300000); but couldn't see the inprogress files to avro files.
I've awaited the main thread for an hour as well but no luck.
Any idea what is stopping in-progress files moving to finished state?
This problem is mainly because Source is a BOUNDED Source. The execution of the entire Flink Job is over before the Checkpoint has been executed.
You can refer to the following example to generate User records instead of fromCollection
/** Data-generating source function. */
public static final class Generator
implements SourceFunction<Tuple2<Integer, Integer>>, CheckpointedFunction {
private static final long serialVersionUID = -2819385275681175792L;
private final int numKeys;
private final int idlenessMs;
private final int recordsToEmit;
private volatile int numRecordsEmitted = 0;
private volatile boolean canceled = false;
private ListState<Integer> state = null;
Generator(final int numKeys, final int idlenessMs, final int durationSeconds) {
this.numKeys = numKeys;
this.idlenessMs = idlenessMs;
this.recordsToEmit = ((durationSeconds * 1000) / idlenessMs) * numKeys;
}
#Override
public void run(final SourceContext<Tuple2<Integer, Integer>> ctx) throws Exception {
while (numRecordsEmitted < recordsToEmit) {
synchronized (ctx.getCheckpointLock()) {
for (int i = 0; i < numKeys; i++) {
ctx.collect(Tuple2.of(i, numRecordsEmitted));
numRecordsEmitted++;
}
}
Thread.sleep(idlenessMs);
}
while (!canceled) {
Thread.sleep(50);
}
}
#Override
public void cancel() {
canceled = true;
}
#Override
public void initializeState(FunctionInitializationContext context) throws Exception {
state =
context.getOperatorStateStore()
.getListState(
new ListStateDescriptor<Integer>(
"state", IntSerializer.INSTANCE));
for (Integer i : state.get()) {
numRecordsEmitted += i;
}
}
#Override
public void snapshotState(FunctionSnapshotContext context) throws Exception {
state.clear();
state.add(numRecordsEmitted);
}
}
}

EXPECTED BEGIN_ARRAY BUT WAS BEGIN_OBJECT AT LINE 1 COLUMN 2 PATH $22

I want to access JSON array . so I created 2 Object !!Have a look at my code , Url
Url-cricapi.com/api/matches/?apikey=JimJAfsmRGOnDpCrRrqO6htlilg1
My MatchesArrayClass
package com.piyushjaiswal.jsonpractis;
public class MatchesArray {
private Matches matches;
private provider provider2;
public MatchesArray(Matches matches, provider provider2) {
this.matches = matches;
this.provider2 = provider2;
}
public Matches getMatches() {
return matches;
}
public void setMatches(Matches matches) {
this.matches = matches;
}
public provider getProvider2() {
return provider2;
}
public void setProvider2(provider provider2) {
this.provider2 = provider2;
}
}
Matches Class
package com.piyushjaiswal.jsonpractis;
import com.google.gson.annotations.SerializedName;
public class Matches {
private int unique_id;
private String date;
private String dateTimeGMT;
#SerializedName("team-1")
private String team1;
#SerializedName("team-2")
private String team2;
private String type;
private String toss_winner_team;
private boolean squad;
private boolean matchStarted;
public int getUnique_id() {
return unique_id;
}
public void setUnique_id(int unique_id) {
this.unique_id = unique_id;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getDateTimeGMT() {
return dateTimeGMT;
}
public void setDateTimeGMT(String dateTimeGMT) {
this.dateTimeGMT = dateTimeGMT;
}
public String getTeam1() {
return team1;
}
public void setTeam1(String team1) {
this.team1 = team1;
}
public String getTeam2() {
return team2;
}
public void setTeam2(String team2) {
this.team2 = team2;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getToss_winner_team() {
return toss_winner_team;
}
public void setToss_winner_team(String toss_winner_team) {
this.toss_winner_team = toss_winner_team;
}
public boolean isSquad() {
return squad;
}
public void setSquad(boolean squad) {
this.squad = squad;
}
public boolean isMatchStarted() {
return matchStarted;
}
public void setMatchStarted(boolean matchStarted) {
this.matchStarted = matchStarted;
}
}
My Provider class
package com.piyushjaiswal.jsonpractis;
public class provider {
private String source;
private String url;
private String pubDate;
public String getSource() {
return source;
}
public void setSource(String source) {
this.source = source;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getPubDate() {
return pubDate;
}
public void setPubDate(String pubDate) {
this.pubDate = pubDate;
}
}
MainActivity Class
package com.piyushjaiswal.jsonpractis;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class MainActivity extends AppCompatActivity {
private TextView textView;
private JsonPlaceHolderApi jsonPlaceHolderApi;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.textview);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://cricapi.com/api/")
.addConverterFactory(GsonConverterFactory.create())
.build();
jsonPlaceHolderApi = retrofit.create(JsonPlaceHolderApi.class);
getMatchList();
}
private void getMatchList() {
Call<List<MatchesArray>> call = jsonPlaceHolderApi.getPosts("JimJAfsmRGOnDpCrRrqO6htlilg1");
call.enqueue(new Callback<List<MatchesArray>>() {
#Override
public void onResponse(Call<List<MatchesArray>> call, Response<List<MatchesArray>> response) {
if(!response.isSuccessful()){
textView.setText(response.message() + "123");
return;
}
List<MatchesArray> list = response.body();
textView.setText(list.get(0).getMatches().getDate());
}
#Override
public void onFailure(Call<List<MatchesArray>> call, Throwable t) {
textView.setText(t.getMessage() +"22");
}
});
}
}
But output on screenshot is
"Expected BEGIB_ARRAY but was BEGIN_OBJECT at line 1 column 2 patg $2"
Your JSON syntax is wrong. The response starts with {"matches":[, this means it is an object, with the parameter matches that is of type match[].
So, you need a new class along the lines of:
public class MatchesWrapper {
private List<Matches> matches;
}
And change all your Call<List<MatchesArray>> to Call<MatchesWrapper>.
The error you received tells you this. You expected an array of Matches (Expected BEGIN_ARRAY), but instead received an object (was BEGIN_OBJECT).

camel jpa #Consumed is not being called

I'm trying to use #Consumed on jpa entity with camel.
this is my route :
<route id="incomingFileHandlerRoute">
<from
uri="jpa://com.menora.inbal.incomingFileHandler.Jpa.model.MessageToDB?consumer.nativeQuery=select
* from file_message where mstatus = 'TODO'&consumer.delay=5000&consumeDelete=false&consumeLockEntity=true&consumer.SkipLockedEntity=true" />
<to uri="bean:incomingFileHandler" />
</route>
and my entity:
#Entity
#Table(name = "file_message")
public class MessageToDB implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
private String uuid;
private String fileName;
private String body;
private String mstatus;
#Temporal(TemporalType.TIMESTAMP)
private Date mtimestamp;
#Consumed
public void updateMstatus() {
setMstatus(MessageStatus.DONE.name());
}
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public String getMstatus() {
return mstatus;
}
public void setMstatus(String mstatus) {
this.mstatus = mstatus;
}
public Date getMtimestamp() {
return mtimestamp;
}
public void setMtimestamp(Date mtimestamp) {
this.mtimestamp = mtimestamp;
}
}
I do get to incomingFileHandler bean with results from db but I do not get to the Consumed method updateMstatus . The incomingFileHandler bean is getting called continuously as always there are results from db
I have a similar implementation with camel-jpa and annotations #Consumed and #PreConsumed in the entity but none of these methods is called.
I look the camel-jpa source code and found this in JpaConsumer.java:
protected DeleteHandler<Object> createPreDeleteHandler() {
// Look for #PreConsumed to allow custom callback before the Entity has been consumed
final Class<?> entityType = getEndpoint().getEntityType();
if (entityType != null) {
// Inspect the method(s) annotated with #PreConsumed
if entityType is null the entity class inst inspect the method annotated with #Consumed and #PreConsumed.
Solution: add entityType=com.xx.yy.MessageToDB to your URI to set Endpoint Entity type.

Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 6 column 11 path $.data

i have json, and i want to retrieve using gson,below my json :
{
"status_code":1,
"message":"response ok",
"api_version":"v1",
"api_endpoint_name":"category_island",
"data": [
{
"island_id":1,
"island_name":"Anambas",
"categories": [
{"id":1, "category_name":"Culinary"},
{"id":2, "category_name":"Hotel"},
{"id":3, "category_name":"Culture"}
]
}
]
}
after that i create model to retrieve it :
public class ModelCategory {
#SerializedName("status_code")
public String status_code;
#SerializedName("message")
public String message;
#SerializedName("api_version")
public String api_version;
#SerializedName("api_endpoint_name")
public String api_endpoint_name;
#SerializedName("data")
public data data;
public static class data {
#SerializedName("id")
public String id;
#SerializedName("island_name")
public String island_name;
#SerializedName("categories")
public List<categories> categories;
public static class categories {
#SerializedName("ID")
public String id;
#SerializedName("category_name")
public String category_name;
}
}
}
and this is my code to retrieve json, i'm using gson:
ModelCategory model = new Gson().fromJson(models, ModelCategory.class);
ArrayList<ModelCategory.data.categories> _model = (ArrayList<ModelCategory.data.categories>) model.data.categories;
but when i run always display error in ModelCategory , error like below :
java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 6 column 11 path $.data
You need to change the model. Try this -
Category.java
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Category {
#SerializedName("id")
#Expose
private Integer id;
#SerializedName("category_name")
#Expose
private String categoryName;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getCategoryName() {
return categoryName;
}
public void setCategoryName(String categoryName) {
this.categoryName = categoryName;
}
#Override
public String toString() {
return "Category [id=" + id + ", categoryName=" + categoryName + "]";
}
}
Datum.java
import java.util.ArrayList;
import java.util.List;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Datum {
#SerializedName("island_id")
#Expose
private Integer islandId;
#SerializedName("island_name")
#Expose
private String islandName;
#SerializedName("categories")
#Expose
private List<Category> categories = new ArrayList<Category>();
public Integer getIslandId() {
return islandId;
}
public void setIslandId(Integer islandId) {
this.islandId = islandId;
}
public String getIslandName() {
return islandName;
}
public void setIslandName(String islandName) {
this.islandName = islandName;
}
public List<Category> getCategories() {
return categories;
}
public void setCategories(List<Category> categories) {
this.categories = categories;
}
#Override
public String toString() {
return "Datum [islandId=" + islandId + ", islandName=" + islandName
+ ", categories=" + categories + "]";
}
}
Example.java
import java.util.ArrayList;
import java.util.List;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Example {
#SerializedName("status_code")
#Expose
private Integer statusCode;
#SerializedName("message")
#Expose
private String message;
#SerializedName("api_version")
#Expose
private String apiVersion;
#SerializedName("api_endpoint_name")
#Expose
private String apiEndpointName;
#SerializedName("data")
#Expose
private List<Datum> data = new ArrayList<Datum>();
public Integer getStatusCode() {
return statusCode;
}
public void setStatusCode(Integer statusCode) {
this.statusCode = statusCode;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getApiVersion() {
return apiVersion;
}
public void setApiVersion(String apiVersion) {
this.apiVersion = apiVersion;
}
public String getApiEndpointName() {
return apiEndpointName;
}
public void setApiEndpointName(String apiEndpointName) {
this.apiEndpointName = apiEndpointName;
}
public List<Datum> getData() {
return data;
}
public void setData(List<Datum> data) {
this.data = data;
}
#Override
public String toString() {
return "Example [statusCode=" + statusCode + ", message=" + message
+ ", apiVersion=" + apiVersion + ", apiEndpointName="
+ apiEndpointName + ", data=" + data + "]";
}
}
Now you can test it as -
Main.java
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.testgson.beans.Example;
public class Main {
private static Gson gson;
static {
gson = new GsonBuilder().create();
}
/**
* #param args
*/
public static void main(String[] args) {
String s = "{\"status_code\":1,\"message\":\"response ok\",\"api_version\":\"v1\",\"api_endpoint_name\":\"category_island\",\"data\":[{\"island_id\":1,\"island_name\":\"Anambas\",\"categories\":[{\"id\":1,\"category_name\":\"Culinary\"},{\"id\":2,\"category_name\":\"Hotel\"},{\"id\":3,\"category_name\":\"Culture\"}]}]}";
Example info = gson.fromJson(s, Example.class);
System.out.println(info);
}
}
Result is -
Example [statusCode=1, message=response ok, apiVersion=v1, apiEndpointName=category_island, data=[Datum [islandId=1, islandName=Anambas, categories=[Category [id=1, categoryName=Culinary], Category [id=2, categoryName=Hotel], Category [id=3, categoryName=Culture]]]]]

Resources