I am creating REST API using spring framework. My entity is based on one table and REST API is supposed to be invoked using POST operation with below JSON structure. Can someone explain me how to map the entity class so that it can consume below-shown json.
Since my entity is based on only one table, I am not able to understand how can it create nested json objects for same table properties.
{
"process_ar_receipt": {
"message_header": {
"source_system_guid": "DDED-DBCD-REV-E1F4343DB3434",
"source_system": "MeSo_TravelAds"
},
"receipt_header": {
"customer_number": "123",
"source_receipt_number": "TESTRCPT_1523",
}
}
}
you could use Gson to convert the json to a DTO
https://jarroba.com/gson-json-java-ejemplos/
pseudo code
assuming your Entity class as
#Entity(name="foo")
class Data{
#Id
private String source_system_guid;
#Column
private String source_system;
#Column
private String customer_number;
#Column
private String source_receipt_number;
public Data() {}
public Data(String ssId, String sourceSystm, String custNum, String srcRcptNum) {
this.source_system_guid = ssId;
this.source_system = sourceSystm;
this.customer_number = custNum;
this.source_receipt_number = srcRcptNum;
}
public String getSource_system_guid() {
return source_system_guid;
}
public void setSource_system_guid(String source_system_guid) {
this.source_system_guid = source_system_guid;
}
public String getSource_system() {
return source_system;
}
public void setSource_system(String source_system) {
this.source_system = source_system;
}
public String getCustomer_number() {
return customer_number;
}
public void setCustomer_number(String customer_number) {
this.customer_number = customer_number;
}
public String getSource_receipt_number() {
return source_receipt_number;
}
public void setSource_receipt_number(String source_receipt_number) {
this.source_receipt_number = source_receipt_number;
}
}
Now since your DTO/BO i.e. Data Transfer Object or Business Object is different from the actual entity we will create the required BO object as below
class DataTO{
#JsonProperty("process_ar_receipt")
private ReceiptTO receiptTO=new ReceiptTO();
public ReceiptTO getReceiptTO() {
return receiptTO;
}
public void setReceiptTO(ReceiptTO receiptTO) {
this.receiptTO = receiptTO;
}
}
class ReceiptTO{
#JsonProperty("message_header")
private MessageHeader messageHeder = new MessageHeader();
#JsonProperty("receipt_header")
private ReceiptHeader receiptHeder = new ReceiptHeader();
public MessageHeader getMessageHeder() {
return messageHeder;
}
public void setMessageHeder(MessageHeader messageHeder) {
this.messageHeder = messageHeder;
}
public ReceiptHeader getReceiptHeder() {
return receiptHeder;
}
public void setReceiptHeder(ReceiptHeader receiptHeder) {
this.receiptHeder = receiptHeder;
}
}
class MessageHeader{
#JsonProperty("source_System_Guid")
private String sourceSystemId;
#JsonProperty("system_Id")
private String systemId;
public String getSourceSystemId() {
return sourceSystemId;
}
public void setSourceSystemId(String sourceSystemId) {
this.sourceSystemId = sourceSystemId;
}
public String getSystemId() {
return systemId;
}
public void setSystemId(String systemId) {
this.systemId = systemId;
}
}
class ReceiptHeader{
#JsonProperty("customer_number")
private String customerNumber;
#JsonProperty("source_rcpt_number")
private String sourceReceiptNumber;
public String getCustomerNumber() {
return customerNumber;
}
public void setCustomerNumber(String customerNumber) {
this.customerNumber = customerNumber;
}
public String getSourceReceiptNumber() {
return sourceReceiptNumber;
}
public void setSourceReceiptNumber(String sourceReceiptNumber) {
this.sourceReceiptNumber = sourceReceiptNumber;
}
}
The #JsonProperty annotation is imported from org.codehaus.jackson.annotate.JsonProperty; i.e from jackson jar
Now a Simple Test class to demo DTO/BO back and forth Entity conversion
public class Test{
public static void main(String[] args) throws JsonGenerationException, JsonMappingException, IOException {
List<Data> datas = new ArrayList<Data>();
datas.add(new Data("DDED-DBCD-REV-E1F4343DB3434","MeSo_TravelAds","123","TESTRCPT_1523"));
datas.add(new Data("ADED-EWQD-REV-E1F4343YG3434","FooSo_MusicAds","132","TESTRCPT_1523"));
datas.add(new Data("YDED-YUTR-REV-E1F43UIDB3434","BarSo_HealthAds","143","TESTRCPT_1523"));
List<DataTO> dataTOs = new ArrayList<DataTO>();
for (Data data : datas) {
DataTO dataTO = new DataTO();
dataTO.getReceiptTO().getMessageHeder().setSourceSystemId(data.getSource_system_guid());
dataTO.getReceiptTO().getMessageHeder().setSystemId(data.getSource_system());
dataTO.getReceiptTO().getReceiptHeder().setCustomerNumber(data.getCustomer_number());
dataTO.getReceiptTO().getReceiptHeder().setSourceReceiptNumber(data.getSource_receipt_number());
dataTOs.add(dataTO);
}
ObjectMapper mapper = new ObjectMapper();
String str = mapper.writeValueAsString(dataTOs);
System.out.println(str);
}
}
This will give you below result
[
{
"process_ar_receipt":{
"message_header":{
"source_System_Guid":"DDED-DBCD-REV-E1F4343DB3434",
"system_Id":"MeSo_TravelAds"
},
"receipt_header":{
"customer_number":"123",
"source_rcpt_number":"TESTRCPT_1523"
}
}
},
{
"process_ar_receipt":{
"message_header":{
"source_System_Guid":"ADED-EWQD-REV-E1F4343YG3434",
"system_Id":"FooSo_MusicAds"
},
"receipt_header":{
"customer_number":"132",
"source_rcpt_number":"TESTRCPT_1523"
}
}
},
{
"process_ar_receipt":{
"message_header":{
"source_System_Guid":"YDED-YUTR-REV-E1F43UIDB3434",
"system_Id":"BarSo_HealthAds"
},
"receipt_header":{
"customer_number":"143",
"source_rcpt_number":"TESTRCPT_1523"
}
}
}
]
similarly the other conversion
String input = "{ \r\n" +
" \"process_ar_receipt\":{ \r\n" +
" \"message_header\":{ \r\n" +
" \"source_System_Guid\":\"ADED-EWQD-REV-E1F4343YG3434\",\r\n" +
" \"system_Id\":\"FooSo_MusicAds\"\r\n" +
" },\r\n" +
" \"receipt_header\":{ \r\n" +
" \"customer_number\":\"132\",\r\n" +
" \"source_rcpt_number\":\"TESTRCPT_1523\"\r\n" +
" }\r\n" +
" }\r\n" +
" }";
DataTO dataTO = mapper.readValue(input, DataTO.class);
System.out.println(dataTO.getReceiptTO().getMessageHeder().getSourceSystemId());
System.out.println(dataTO.getReceiptTO().getMessageHeder().getSystemId());
System.out.println(dataTO.getReceiptTO().getReceiptHeder().getCustomerNumber());
System.out.println(dataTO.getReceiptTO().getReceiptHeder().getSourceReceiptNumber());
this will print
ADED-EWQD-REV-E1F4343YG3434
FooSo_MusicAds
132
TESTRCPT_1523
You dont have to use the mapper code you can directly add the jackson converter as HttpMessageConverted which will convert the JSON to java object automatically
#Configuration
#EnableWebMvc
public class WebConfiguration extends WebMvcConfigurerAdapter {
... other configurations
#Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
builder.serializationInclusion(JsonInclude.Include.NON_NULL);
builder.propertyNamingStrategy(PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES);
builder.serializationInclusion(Include.NON_EMPTY);
builder.indentOutput(true).dateFormat(new SimpleDateFormat("yyyy-MM-dd"));
converters.add(new MappingJackson2HttpMessageConverter(builder.build()));
converters.add(new MappingJackson2XmlHttpMessageConverter(builder.createXmlMapper(true).build()));
}
}
Related
i have below resttempalte which invokes rest controller of another service..
#Override
public ResponseEntity<String> callRestAPI(APIReqDataMO apiReqDataMO) {
String apiURL = URIGenerator.getAPIURL(apiReqDataMO);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("Accept", MediaType.APPLICATION_JSON_VALUE);
HttpEntity<?> request = new HttpEntity<>(apiReqDataMO.getRequestObject(), headers);
ResponseEntity<String> httpRes = restTemplate.postForEntity(apiURL, request, String.class);
return httpRes;
}
and in my service i have controller, which consumes above request..
#RequestMapping(value = "/targetService/createUser", method = RequestMethod.POST, consumes = "application/json")
public String fuzzerServiceAge(UserMO userMO) {
System.out.println("---------------------age is -------------------------" + userMO.getAge());
if (userMO.getAge() > 0) {
System.out.println("error age greater than 0 ");
return "invalid user age";
} else if (userMO.getAge() == 0) {
return "invalid user age";
}
return "user added successfully";
}
when i try my test.. the age which i am pushing through rest template is not getting mapped..and i am getting age as 0 always in my system.out.. what could be wrong in my code... and is there anything missing from configuration perspective..
EDIT -
public class APIReqDataMO {
private String restAPIURL;
private Object[] pathParam;
private Object[] requestParam;
private String requestType;
private String paramType;
private Object requestObject;
public String getParamType() {
return paramType;
}
public void setParamType(String paramType) {
this.paramType = paramType;
}
public String getRequestType() {
return requestType;
}
public void setRequestType(String requestType) {
this.requestType = requestType;
}
public Object getRequestObject() {
return requestObject;
}
public void setRequestObject(Object requestObject) {
this.requestObject = requestObject;
}
public String getRestAPIURL() {
return restAPIURL;
}
public void setRestAPIURL(String restAPIURL) {
this.restAPIURL = restAPIURL;
}
public Object[] getPathParam() {
return pathParam;
}
public void setPathParam(Object[] pathParam) {
this.pathParam = pathParam;
}
public Object[] getRequestParam() {
return requestParam;
}
public void setRequestParam(Object[] requestParam) {
this.requestParam = requestParam;
}
}
controller
#PostMapping("/targetService/createUser")
public String fuzzerServiceAge(UserMO userMO) {
System.out.println("--------------------- age is -------------------------" + userMO.getAge());
if (userMO.getAge() > 0) {
// return ResponseEntity.ok("Hello World!");
} else if (userMO.getAge() == 0) {
System.out.println(" it is else block");
// return ResponseEntity.badRequest().build();
}
// return ResponseEntity.ok("user added successfully!");
return "user added successfully";
}
usermo
public class UserMO {
#JsonProperty("name")
private String name;
#JsonProperty("age")
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
Issue
There is an issue in API implementation. You are creating POST API and when the user will invoke this API by passing UserMO in the request body then mapping won't happen because the #RequestBody annotation is missing.
#PostMapping("/targetService/createUser")
public String fuzzerServiceAge(UserMO userMO) {
System.out.println("--------------------- age is -------------------------" + userMO.getAge());
if (userMO.getAge() > 0) {
// return ResponseEntity.ok("Hello World!");
} else if (userMO.getAge() == 0) {
System.out.println(" it is else block");
// return ResponseEntity.badRequest().build();
}
// return ResponseEntity.ok("user added successfully!");
return "user added successfully";
}
Solution
If you are using #RestController annotation on top of the controller class then add #RequestBody annotation before UserMO userMO and try again.
Like this
#PostMapping("/targetService/createUser")
public String fuzzerServiceAge(#RequestBody UserMO userMO) {
//logic
}
if you are using #Controller annotation on top of the controller class then add #ResponseBody annotation on top of method fuzzerServiceAge() and #RequestBody annotation before UserMO userMO and try again.
Like this
#PostMapping("/targetService/createUser")
#ResponseBody
public String fuzzerServiceAge(#RequestBody UserMO userMO) {
//logic
}
Is there any way to make a super-class document (e.g. index name = user) and create two child classes (Admin, Guest) to save all this to user index but with different fields? E.g. Add to super-class field type and based on this field fetch right entity? ELK 7.19, Spring Data 4.3.1.
You can do that. Make the base class abstract. I have this in a test setup with the following classes:
#Document(indexName = "type-hints")
public abstract class BaseClass {
#Id
private String id;
#Field(type = FieldType.Text)
private String baseText;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getBaseText() {
return baseText;
}
public void setBaseText(String baseText) {
this.baseText = baseText;
}
#Override
public String toString() {
return "BaseClass{" +
"id='" + id + '\'' +
", baseText='" + baseText + '\'' +
'}';
}
}
public class DerivedOne extends BaseClass {
#Field(type = FieldType.Text)
private String derivedOne;
public String getDerivedOne() {
return derivedOne;
}
public void setDerivedOne(String derivedOne) {
this.derivedOne = derivedOne;
}
#Override
public String toString() {
return "DerivedOne{" +
"derivedOne='" + derivedOne + '\'' +
"} " + super.toString();
}
}
public class DerivedTwo extends BaseClass {
#Field(type = FieldType.Text)
private String derivedTwo;
public String getDerivedTwo() {
return derivedTwo;
}
public void setDerivedTwo(String derivedTwo) {
this.derivedTwo = derivedTwo;
}
#Override
public String toString() {
return "DerivedTwo{" +
"derivedTwo='" + derivedTwo + '\'' +
"} " + super.toString();
}
}
interface TypeHintRepository extends ElasticsearchRepository<BaseClass, String> {
SearchHits<? extends BaseClass> searchAllBy();
}
#RestController
#RequestMapping("/typehints")
public class TypeHintController {
private static final Logger LOGGER = LoggerFactory.getLogger(TypeHintController.class);
private final TypeHintRepository repository;
public TypeHintController(TypeHintRepository repository) {
this.repository = repository;
}
#GetMapping
public void test() {
List<BaseClass> docs = new ArrayList<>();
DerivedOne docOne = new DerivedOne();
docOne.setId("one");
docOne.setBaseText("baseOne");
docOne.setDerivedOne("derivedOne");
docs.add(docOne);
DerivedTwo docTwo = new DerivedTwo();
docTwo.setId("two");
docTwo.setBaseText("baseTwo");
docTwo.setDerivedTwo("derivedTwo");
docs.add(docTwo);
repository.saveAll(docs);
SearchHits<? extends BaseClass> searchHits = repository.searchAllBy();
for (SearchHit<? extends BaseClass> searchHit : searchHits) {
LOGGER.info(searchHit.toString());
}
}
}
Etity
#Entity
public class DateFMail {
#Id
private double balance;
public DateFMail() {
}
public DateFMail(double balance) {this.balance = balance;}
public DateFMail(DateFMail dateFMail) {
}
public double getBalance() { return balance;}
#Override
public String toString() {
return "DateFMail{" +
"balance=" + balance +
'}';
}
}
Service
public interface DateFMailService {
List<DateFMail> findAll();
}
Impl
#Service
public class DateFMailServiceImpl implements DateFMailService {
#Autowired
private DateFMailRepository mailRepository;
#Override
public List<DateFMail> findAll() {
return mailRepository.findAll();
}
}
Repository
#Repository
public interface DateFMailRepository extends JpaRepository<DateFMail, Long> {
#Query(value = "SELECT SUM(balance) \n" +
" FROM agents", nativeQuery = true)
List<DateFMail> findAll();
}
Mail Seder
#Service
public class EmailDos {
#Autowired
private JavaMailSender mailSender;
private DateFMailRepository mailRepository;
String fileDate1 = new SimpleDateFormat("dd.MM.yyyy").format(new Date());
LocalDate today = LocalDate.now();
String fileDate = (today.minusDays(1)).format(DateTimeFormatter.ofPattern("dd MMM"));
String fileDate2 = (today.minusMonths(1)).format(DateTimeFormatter.ofPattern("MMM"));
public void sendMailSum(String from, String to, String subject, String body, String fileToAttach) throws SQLException {
List<DateFMail> list = new ArrayList<>(mailRepository.findAll());
List<DateFMail> list1 = list.stream()
.map(DateFMail::new)
.collect(Collectors.toList());
System.out.println("sending email...................");
System.out.println(list1);
MimeMessagePreparator preparator = new MimeMessagePreparator() {
public void prepare(MimeMessage mimeMessage) throws Exception {
mimeMessage.setFrom(new InternetAddress(from));
mimeMessage.setRecipient(Message.RecipientType.TO, new InternetAddress(to));
mimeMessage.setSubject(subject);
mimeMessage.setText(body);
FileSystemResource file = new FileSystemResource(new File("C:...xlsx"));
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
helper.setFrom("SomeAddress#gmail.com");
helper.setTo(InternetAddress.parse("SomeAddress#gmail.com"));
helper.setText("Good day!\nIn attachment payments for " + fileDate + " с 12.00-00.00" + "\nAmount for " + fileDate1 + list1);
helper.addAttachment("...xlsx", file);
mailSender.send(mimeMessage);
System.out.println("email Fab was successfully sent.....");
}
};
try {
mailSender.send(preparator);
} catch (MailException ex) {
System.err.println(ex.getMessage());
}
}
}
Controller
#Component
public class DateFMailController {
#Autowired
private DateFMailService mailService;
public void saveSum() throws IOException {
saveExcel(mailService.findAll(), "....xlsx");
}
private void saveExcel(List<DateFMail> list, String fileName) throws IOException {
Workbook workbook = new XSSFWorkbook();
CreationHelper createHelper = workbook.getCreationHelper();
Sheet sheet = workbook.createSheet("ECards");
sheet.autoSizeColumn(0);
Row header = sheet.createRow(0);
CellStyle headerStyle = workbook.createCellStyle();
headerStyle.setFillForegroundColor(IndexedColors.LIGHT_BLUE.getIndex());
headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
XSSFFont font = ((XSSFWorkbook) workbook).createFont();
font.setFontName("Arial");
font.setFontHeightInPoints((short) 10);
font.setBold(true);
headerStyle.setFont(font);
Cell headerCell = header.createCell(0);
headerCell.setCellValue("Sum");
headerCell.setCellStyle(headerStyle);
CellStyle style = workbook.createCellStyle();
style.setWrapText(true);
int ix_row=2;
for (DateFMail dateFMail : list) {
Row row = sheet.createRow(ix_row);
Cell cell = row.createCell(0);
cell.setCellValue(dateFMail.getBalance());
cell.setCellStyle(style);
ix_row++;
}
FileOutputStream outputStream = new FileOutputStream(fileName);
workbook.write(outputStream);
workbook.close();
}
}
Save Runer
#Component
public class SaveCardsStartupRunner implements ApplicationRunner {
#Autowired
private ECardController eCardController;
private DateFMailController controller;
// #Autowired
// private EmailDos emailDos;
String fileDate1 = new SimpleDateFormat("dd.MM.yyyy").format(new Date());
LocalDate today = LocalDate.now();
String fileDate = (today.minusDays(1)).format(DateTimeFormatter.ofPattern("dd MMM"));
String fileDate2 = (today.minusMonths(1)).format(DateTimeFormatter.ofPattern("MMM"));
#Override
public void run(ApplicationArguments args) throws Exception {
eCardController.saveCards();
controller.saveSum();
}
}
I have corrected my question. I've pasted all the code here that pertains to my question. For starters, I would like to simply output the Query result of the repository to the console. But in the form that I just posted here, I get a NullPointerException error and says that in a part of the code: controller.saveSum (); - controller = null.
Create a PaymentService class which should contain the method getTotalPayment. Inject this class in EmailSend (tip: please change this class name from EmailSend to EmailSender as class names should be noun) class. And then in PaymentService Class you should interact Data Repository class. Call this getTotalPayment method from the EmailSend class.
I'm trying to build a Spring WebFlux project and realize the follow business logic:
1 - Call an external REST Api using WebClient and parse the Json results using the Models below. It is working OK
2 - To show the Mono results Mono<DeviceList> devices, I'm using the ResponseApi class and returning it, but it is NOT working
I'm getting the follow error:
Response status 406 with reason "Could not find acceptable representation"
Thanks
# Json Result
{
"data": [
{
"id": "5bc3c0efe833d93f401bafa8",
"name": "XXXXX",
"group": "5b8fd1fa0499f54cfa7febb8",
"description": "Geolocalizacao gps",
"payloadType": "None",
"contract": "5bc08be5e833d93f40e1f936",
"keepAlive": 0
}
]
}
# Controller
public class DeviceController{
...
...
#RequestMapping(value = V1 + BASE_URL + "/devices/types", method = GET, produces = APPLICATION_JSON)
public Mono<ServerResponse> getDeviceTypes(){
Mono<DeviceList> devices = deviceService.findDeviceTypes();
ResponseApi r = new ResponseApi();
r.setMessage("Test");
r.setCode("200");
r.setStatus(200);
r.setData(devices);
return ok().body(Mono.just(r), ResponseApi.class);
}
}
# Repository
public Mono<DeviceList> findDeviceTypes() {
return webClient.get()
.uri(DEVICE_TYPES_URL)
.accept(MediaType.APPLICATION_JSON)
.retrieve()
.bodyToMono(DeviceList.class);
}
# Model
public class DeviceList{
#JsonProperty("data")
private List<Device> data;
public List<Device> getData() {
return data;
}
public void setData(List<Device> data) {
this.data = data;
}
}
public class Device{
#JsonProperty("id")
private String id;
#JsonProperty("name")
private String name;
#JsonProperty("group")
private String group;
#JsonProperty("description")
private String description;
#JsonProperty("keepAlive")
private Integer keepAlive;
#JsonProperty("payloadType")
private String payloadType;
#JsonProperty("contract")
private String contract;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGroup() {
return group;
}
public void setGroup(String group) {
this.group = group;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Integer getKeepAlive() {
return keepAlive;
}
public void setKeepAlive(Integer keepAlive) {
this.keepAlive = keepAlive;
}
public String getPayloadType() {
return payloadType;
}
public void setPayloadType(String payloadType) {
this.payloadType = payloadType;
}
public String getContract() {
return contract;
}
public void setContract(String contract) {
this.contract = contract;
}
}
#JsonRootName("data")
public class ResponseApi{
#JsonProperty("status")
private Integer status;
#JsonProperty("code")
private String code;
#JsonProperty("message")
private String message;
#JsonProperty("data")
private Object data;
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}
You can get devices, then in non blocking way, map them to the ResponseApi like that:
#RequestMapping(value = V1 + BASE_URL + "/devices/types", method = GET, produces = APPLICATION_JSON)
public Mono<ServerResponse> getDeviceTypes(){
return deviceService.findDeviceTypes()
.flatMap(devices -> {
ResponseApi r = new ResponseApi();
r.setMessage("Test");
r.setCode("200");
r.setStatus(200);
r.setData(devices);
return ok().body(Mono.just(r), ResponseApi.class);
});
}
Can't figure out why I am getting a NullPointerException on my platform in my Configuration class when I try to print out the object.
Here's the yaml file:
platform:
platformType: CVN
hwVariant:
canesVariant: HW
hullNumber: XXX
tri: INST
Here is my parent object class Configuration.java
public class Configuration {
private Platform platform;
public Configuration() {
}
public Platform getPlatform() {
return platform;
}
public void setPlatform(Platform platform) {
this.platform = platform;
}
#Override
public String toString() {
return platform.toString();
}
}
Here's my Platform.java:
import java.util.Map;
public class Platform {
private String platformType;
private Map<String, String> hwVariant;
private String hullNumber;
private String tri;
public Platform() {
}
public String getPlatformType() {
return platformType;
}
public Map<String, String> getHWVariant() {
return hwVariant;
}
public String getHull() {
return hullNumber;
}
public String getTri() {
return tri;
}
public void setPlatformType(String platformType) {
this.platformType = platformType;
}
public void setHWVariant(Map<String, String> hwVariant) {
this.hwVariant = hwVariant;
}
public void setHullNumber(String hullNumber) {
this.hullNumber = hullNumber;
}
public void setTri(String tri) {
this.tri = tri;
}
#Override
public String toString() {
return "platform: \n" +
" platformType: " + platformType + "\n" +
" hwVariant: " + hwVariant + "\n" +
" hullNumber: " + hullNumber + "\n" +
" tri: " + tri;
}
}
Here's the NullPointerException I'm getting:
File is: E:\workspace_neon\PlatformInterviewer\resources\uswdss-platform.yml
Exception in thread "main" Can't construct a java object for tag:yaml.org,2002:net.progeny.setup.model.Configuration; exception=null
in 'reader', line 1, column 1:
platform:
^
at org.yaml.snakeyaml.constructor.Constructor$ConstructYamlObject.construct(Constructor.java:314)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructObjectNoCheck(BaseConstructor.java:204)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructObject(BaseConstructor.java:193)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructDocument(BaseConstructor.java:159)
at org.yaml.snakeyaml.constructor.BaseConstructor.getSingleData(BaseConstructor.java:146)
at org.yaml.snakeyaml.Yaml.loadFromReader(Yaml.java:524)
at org.yaml.snakeyaml.Yaml.loadAs(Yaml.java:518)
at net.progeny.setup.YamlConfiguration.main(YamlConfiguration.java:28)
Caused by: java.lang.NullPointerException
at net.progeny.setup.model.Configuration.toString(Configuration.java:31)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at org.yaml.snakeyaml.constructor.Constructor$ConstructMapping.constructJavaBean2ndStep(Constructor.java:268)
at org.yaml.snakeyaml.constructor.Constructor$ConstructMapping.construct(Constructor.java:149)
at org.yaml.snakeyaml.constructor.Constructor$ConstructYamlObject.construct(Constructor.java:309)
... 7 more
I just can't seem to get it working when I added the inner nested hwVariant option. If I remove the hwVariant and canesVariant from my yaml file it works fine, albeit without those key value pairs. What am I missing?
Change Getter and Setter method of field 'hwVariant' of class Platform to following.
public Map<String, String> getHwVariant() {
return hwVariant;
}
public void setHwVariant(Map<String, String> hwVariant) {
this.hwVariant = hwVariant;
}
SnakeYaml internally uses jackson to map yaml document into a java object. Jackson internally calls getter and setter method of the fields, so it expects getter and setter to be in standard form.