I need to process a JSON - it has repeating groups I need to convert it to fixed length record
{
"blockType" : "BL-H ",
"blockTypeLength" : "00000031",
"blockId" : "S62951156229900",
"totalNoOfTX" : "001",
"msgblockType" : "TX-S ",
"messageLength" : "00000728",
"noa":[
{
"title":"Behin",
"artist":"LIMP ",
"itunes_link":"http:behind"
},
{
"title":"Alone",
"artist":"ALYSS",
"itunes_link":"http:clk.doubler.com"
}
]
}
Should be converted to BehinLIMP http:behindAloneALYSShttp:clk.doubler.com
I can have one to many such groups in the request
What I have tried -
DataFormat bindy = new BindyFixedLengthDataFormat(myModel.class);
from("direct:testUnmarshall")
.log("${body}")
//.unmarshal().json(JsonLibrary.Jackson, BillingBookingRequest[].class)
.inputType(BillingBookingRequest.class)
.process(new Processor() {
@Override
public void process(Exchange exchange) throws Exception {
try {
BillingBookingRequest responseBody = exchange.getMessage().getBody(BillingBookingRequest.class);
ZvkkRequest requestBody = new ZvkkRequest();
requestBody.setBlockType(responseBody.getBlockType());
requestBody.setBlockTypeLength(responseBody.getBlockTypeLength());
requestBody.setBlockId(responseBody.getBlockId());
requestBody.setTotalNoOfTX(responseBody.getTotalNoOfTX());
requestBody.setMsgblockType(responseBody.getMsgblockType());
requestBody.setMessageLength(responseBody.getMessageLength());
List<DAO> noaList = responseBody.getNoa();
List<DAOFix> repGrp = new ArrayList<>();
for (DAO noa:
noaList) {
DAOFix obj = new DAOFix();
obj.setArtist(noa.getArtist());obj.setTitle(noa.getTitle());obj.setItunes_link(noa.getItunes_link());
repGrp.add(obj);
}
requestBody.setRepeatingGrp(repGrp);
exchange.getOut().setBody(requestBody);
} catch (Exception exception){
System.out.println("EXCEPTION HERE :: "+exception.getMessage());
exception.printStackTrace();
}
}
})
.log("Before marshal ....... ${body}")
.marshal(bindy)
.log("After marshal ....... ${body}")
.to("{{file.path}}fileName=check.dat")
.end();
java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
also observed - org.apache.camel.NoTypeConversionAvailableException: No type converter available to convert from type: myFixedLengthRequestModel to the required type: java.io.InputStream with value myFixedLengthRequestModel[with all the values]
I have used the corresponding models holding the values for json as well as @FixedLengthRecord need help to understand and get this resolved.
public class ZvkkRequest {
@DataField(pos = 1, length=5, align = "L", paddingChar=' ')
private String blockType;
@DataField(pos = 2, length=8, align = "R", paddingChar='0')
private int blockTypeLength;
@DataField(pos = 3, length=15, align = "L", paddingChar=' ')
private String blockId;
@DataField(pos = 4, length=3, align = "R", paddingChar='0')
private int totalNoOfTX;
@DataField(pos = 5, length=5, align = "L", paddingChar=' ')
private String msgblockType;
@DataField(pos = 6, length=8, align = "R", paddingChar='0')
private int messageLength;
@OneToMany(mappedTo = "classpath.DAOFix")
private List<DAOFix> repeatingGrp;
}
class DAOFix {
@DataField(pos = 7, length=5, align = "R", paddingChar=' ')
private String title;
@DataField(pos = 8, length=5, align = "R", paddingChar=' ')
private String artist;
@DataField(pos = 9, length=5, align = "R", paddingChar=' ')
private String itunes_link;
}
Tested this out and it seems @OneToMany
does not seem to work with BindyFixedLengthDataFormat
like it does with BindyCsvDataFormat
this means that you'll likely process the json and create multiple object instances which you can then marshal in to fixed length record with Bindy.
Below is code I used to test this out as well as one way (direct:bindyFixedLenghtProcessed
) to convert single ZvkkRequest
instance to list of ZvkkRequestFixedLenght
instances which you can then marshal to BindyFixedLengthDataFormat
public class ExampleTests extends CamelTestSupport {
@Test
public void bindyCSVTest(){
// Test bindy @OneToMany with BindyCsvDataFormat
template.sendBody("direct:bindyCSV", testJson);
}
@Test
public void bindyFixedLenghtTest(){
// Test bindy @OneToMany with BindyFixedLengthDataFormat
template.sendBody("direct:bindyFixedLenght", testJson);
}
@Test
public void bindyFixedLenghtProcessedTest(){
// Test workaraound
template.sendBody("direct:bindyFixedLenghtProcessed", testJson);
}
@Override
protected RoutesBuilder createRouteBuilder() throws Exception {
return new RouteBuilder(){
@Override
public void configure() throws Exception {
// Doesn't seem to work with OneToMany
DataFormat bindyCSV = new BindyCsvDataFormat(ZvkkRequest.class);
from("direct:bindyCSV")
.unmarshal().json(JsonLibrary.Jackson, ZvkkRequest.class)
.marshal(bindyCSV)
.log("${body}");
DataFormat bindyFixedLenght = new BindyFixedLengthDataFormat(ZvkkRequest.class);
from("direct:bindyFixedLenght")
.unmarshal().json(JsonLibrary.Jackson, ZvkkRequest.class)
.marshal(bindyFixedLenght)
.log("${body}");
DataFormat bindyFixedLenght2 = new BindyFixedLengthDataFormat(ZvkkRequestFixedLenght.class);
from("direct:bindyFixedLenghtProcessed")
.unmarshal().json(JsonLibrary.Jackson, ZvkkRequest.class)
.process(new Processor(){
@Override
public void process(Exchange exchange) throws Exception {
ZvkkRequest body = exchange.getMessage()
.getBody(ZvkkRequest.class);
List<ZvkkRequestFixedLenght> requests = new ArrayList<>();
for (DAOFix it : body.noa) {
ZvkkRequestFixedLenght request = new ZvkkRequestFixedLenght();
request.blockType = body.blockType;
request.blockTypeLength = body.blockTypeLength;
request.blockId = body.blockId;
request.totalNoOfTX = body.totalNoOfTX;
request.msgblockType = body.msgblockType;
request.messageLength = body.messageLength;
request.artist = it.artist;
request.title = it.title;
request.itunesLink = it.itunesLink;
requests.add(request);
}
exchange.getMessage().setBody(requests);
}
})
.marshal(bindyFixedLenght2)
.log("${body}");
}
};
}
String testJson = "{" +
" \"blockType\" : \"BL-H \"," +
" \"blockTypeLength\" : \"00000031\"," +
" \"blockId\" : \"S62951156229900\"," +
" \"totalNoOfTX\" : \"001\"," +
" \"msgblockType\" : \"TX-S \"," +
" \"messageLength\" : \"00000728\"," +
" \"noa\":[" +
" {" +
" \"title\":\"Behin\"," +
" \"artist\":\"LIMP \"," +
" \"itunes_link\":\"http:behind\"" +
" }," +
" {" +
" \"title\":\"Alone\"," +
" \"artist\":\"ALYSS\"," +
" \"itunes_link\":\"http:clk.doubler.com\"" +
" }" +
" ]" +
"}";
}
bindyFixedLenghtProcessedTest logs following:
BL-H 00000031S62951156229900001TX-S 00000728BehinLIMP http:behind
BL-H 00000031S62951156229900001TX-S 00000728AloneALYSS http:clk.doubler.com
In case you want to have these on a single line you can try to marshal ZvkkRequest
and DAOFix
separately and use string concatenation to combine the unmarshalled DAOFix
entries to unmarshalled ZvkkRequest
.
ZvkkRequest.java
@FixedLengthRecord
@CsvRecord(separator=",")
public class ZvkkRequest {
@DataField(pos = 1, length = 5, align = "L", paddingChar = ' ')
public String blockType;
@DataField(pos = 2, length = 8, align = "R", paddingChar = '0')
public int blockTypeLength;
@DataField(pos = 3, length = 15, align = "L", paddingChar = ' ')
public String blockId;
@DataField(pos = 4, length = 3, align = "R", paddingChar = '0')
public int totalNoOfTX;
@DataField(pos = 5, length = 5, align = "L", paddingChar = ' ')
public String msgblockType;
@DataField(pos = 6, length = 8, align = "R", paddingChar = '0')
public int messageLength;
@OneToMany
public List<DAOFix> noa;
}
DAOFix.java
public class DAOFix {
@DataField(pos = 7, length=5, align = "R", paddingChar=' ')
public String title;
@DataField(pos = 8, length=5, align = "R", paddingChar=' ')
public String artist;
@JsonProperty("itunes_link")
@DataField(pos = 9, length=30, align = "R", paddingChar=' ')
public String itunesLink;
}
ZvkkRequestFixedLenght.java
@CsvRecord(separator=",")
@FixedLengthRecord
public class ZvkkRequestFixedLenght {
@DataField(pos = 1, length = 5, align = "L", paddingChar = ' ')
public String blockType;
@DataField(pos = 2, length = 8, align = "R", paddingChar = '0')
public int blockTypeLength;
@DataField(pos = 3, length = 15, align = "L", paddingChar = ' ')
public String blockId;
@DataField(pos = 4, length = 3, align = "R", paddingChar = '0')
public int totalNoOfTX;
@DataField(pos = 5, length = 5, align = "L", paddingChar = ' ')
public String msgblockType;
@DataField(pos = 6, length = 8, align = "R", paddingChar = '0')
public int messageLength;
@DataField(pos = 7, length=5, align = "R", paddingChar=' ')
public String title;
@DataField(pos = 8, length=5, align = "R", paddingChar=' ')
public String artist;
@DataField(pos = 9, length=30, align = "R", paddingChar=' ')
public String itunesLink;
}