Jackson XML parsing MismatchedInputException - maven

I want to parse Below XML file into Java Object using Jackson. But it shows MismatchedInputException message is become null. I specified feild that I need in Employee class. And using these fields I need to create Employee objects.
d.xml -> the input xml file
<Messages>
<Message>
<Uumid>45</Uumid>
<UumidSuffix>ER.79</UumidSuffix>
<CreationDate>20-05-2020</CreationDate>
<Data>FRHF#%^G</Data>
</Message>
<Message>
<Uumid>89</Uumid>
<UumidSuffix>RT.12</UumidSuffix>
<CreationDate>26-05-2020</CreationDate>
<Data>FGRH#%^</Data>
</Message>
</Messages>
Messages.java
package org.example;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
import java.lang.annotation.Documented;
import java.util.Arrays;
#JacksonXmlRootElement(localName ="Messages")
public final class Messages {
#JacksonXmlElementWrapper(localName = "Message",useWrapping = true)
private Message[] message;
public Messages(){}
public Messages(Message[] message){
this.message=message;
}
public Message[] getMessage() {
return message;
}
public void setMessage(Message[] message) {
this.message = message;
}
#Override
public String toString() {
return "Messages{" +
"message=" + Arrays.toString(message) +
'}';
}
}
Message.java
package org.example;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import javax.xml.bind.annotation.XmlAccessorOrder;
public class Message {
#JacksonXmlProperty(localName = "Uumid")
private String uumid;
#JacksonXmlProperty(localName = "UumidSuffix")
private String uumidSuffix;
#JacksonXmlProperty(localName = "CreationDate")
private String creationDate;
public Message() {}
public Message(String uumid,String uumidSuffix,String creationDate){
this.uumid=uumid;
this.uumidSuffix=uumidSuffix;
this.creationDate=creationDate;
}
public String getUumid() {
return uumid;
}
public void setUumid(String uumid) {
this.uumid = uumid;
}
public String getUumidSuffix() {
return uumidSuffix;
}
public void setUumidSuffix(String uumidSuffix) {
this.uumidSuffix = uumidSuffix;
}
public String getCreationDate() {
return creationDate;
}
public void setCreationDate(String creationDate) {
this.creationDate = creationDate;
}
#Override
public String toString() {
return "Message{" +
"uumid='" + uumid + '\'' +
", uumidSuffix='" + uumidSuffix + '\'' +
", CreationDate='" + creationDate + '\'' +
'}';
}
}
Parser.java
package org.example;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import org.apache.commons.lang3.StringUtils;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
public class Parser {
public static void main(String[] args) throws IOException {
ObjectMapper objectMapper=new XmlMapper();
Messages messages=objectMapper.readValue(StringUtils.toEncodedString(Files.readAllBytes(Paths.get("disk/d.xml")), StandardCharsets.UTF_8),Messages.class);
System.out.println(messages);
}
}
when executes this error shows
Exception in thread "main" com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `org.example.Message` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('asdf')
at [Source: (StringReader); line: 3, column: 20] (through reference chain: org.example.Messages["Message"]->java.lang.Object[][0])
at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:63)
at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1455)
at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1081)
at com.fasterxml.jackson.databind.deser.ValueInstantiator._createFromStringFallbacks(ValueInstantiator.java:371)
at com.fasterxml.jackson.databind.deser.std.StdValueInstantiator.createFromString(StdValueInstantiator.java:323)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromString(BeanDeserializerBase.java:1408)
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:176)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:166)
at com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.deserialize(ObjectArrayDeserializer.java:195)
at com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.deserialize(ObjectArrayDeserializer.java:21)
at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:129)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:293)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:156)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4524)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3466)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3434)
at org.example.Parser.main(Parser.java:17)
Process finished with exit code 1
maven dependencies
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>2.11.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.11.2</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.5</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.11.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.11.2</version>
</dependency>
</dependencies>

Your current code tells Jackson that your messages should be wrapped into a wrapper tag, so it expects XML that looks something like this:
<Messages>
<Message> <!-- this is the wrapper -->
<Message>
<Uumid>...</Uumid>
...
</Message>
<Message>
...
</Message>
</Message>
</Messages>
To fix this, you'll have to tell Jaskcon to not use the wrapper, and that the children are called "Message". In your Messages class you have to update annotations on the message field to the following:
#JacksonXmlElementWrapper(useWrapping = false)
#JacksonXmlProperty(localName = "Message")
private Message[] message;
(BTW, why not call this field messages?)

Related

Optimistic locking Test in spring data JPA

I'm trying to test the optimistic locking mechanism in spring data jpa by loading a certain entity twice using findBy function, then updating the first one and asserting that when the second one is updated, it will throw an OptimisticLockingFailureException.
But the problem is that no exception is thrown and the second update is done successfully.
After investigation i found that findBy function hits the database only the first time and caches the returned entity. and when i call it again it returns cached entity. which means that both loaded entities are equal. so the first update reflects in both entities making the second entity does not have the stale data.
so, how do i force loading the second entity from the data base in the second findBy function call ?
Here is my code:-
Test class
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.dao.OptimisticLockingFailureException;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
#DataJpaTest
#AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
class PersistenceTests {
#Autowired
private ProductRepository repository;
private ProductEntity savedEntity;
#DynamicPropertySource
static void databaseProperties(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", () -> "jdbc:mysql://localhost:3306/code_snippet");
registry.add("spring.datasource.username", () -> "root");
registry.add("spring.datasource.password", () -> "System");
registry.add("spring.jpa.hibernate.ddl-auto", () -> "create-drop");
}
#BeforeEach
void setupDb() {
repository.deleteAll();
ProductEntity entity = new ProductEntity(1, "n", 1);
savedEntity = repository.save(entity);
assertEqualsProduct(entity, savedEntity);
}
#Test
void optimisticLockError() {
// Store the saved entity in two separate entity objects
ProductEntity entity1 = repository.findById(savedEntity.getId()).get();
ProductEntity entity2 = repository.findById(savedEntity.getId()).get();
// Update the entity using the first entity object
entity1.setName("n1");
repository.save(entity1);
// Update the entity using the second entity object.
// This should fail since the second entity now holds an old version number,
// i.e. an Optimistic Lock Error
assertThrows(OptimisticLockingFailureException.class, () -> {
entity2.setName("n2");
repository.save(entity2);
});
// Get the updated entity from the database and verify its new sate
ProductEntity updatedEntity = repository.findById(savedEntity.getId()).get();
assertEquals(1, (int) updatedEntity.getVersion());
assertEquals("n1", updatedEntity.getName());
}
private void assertEqualsProduct(ProductEntity expectedEntity, ProductEntity actualEntity) {
assertEquals(expectedEntity.getId(), actualEntity.getId());
assertEquals(expectedEntity.getVersion(), actualEntity.getVersion());
assertEquals(expectedEntity.getProductId(), actualEntity.getProductId());
assertEquals(expectedEntity.getName(), actualEntity.getName());
assertEquals(expectedEntity.getWeight(), actualEntity.getWeight());
}
}
Entity
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Version;
#Entity
#Table(name = "product")
public class ProductEntity {
#Id
#GeneratedValue
private Integer id;
#Version
private Integer version;
private int productId;
private String name;
private int weight;
public ProductEntity() {
}
public ProductEntity(int productId, String name, int weight) {
this.productId = productId;
this.name = name;
this.weight = weight;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getVersion() {
return version;
}
public void setVersion(Integer version) {
this.version = version;
}
public int getProductId() {
return productId;
}
public void setProductId(int productId) {
this.productId = productId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
}
Repository
import java.util.Optional;
import org.springframework.data.repository.PagingAndSortingRepository;
public interface ProductRepository extends PagingAndSortingRepository<ProductEntity, Integer> {
Optional<ProductEntity> findByProductId(int productId);
}
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.2</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.javaworld.codesnippet</groupId>
<artifactId>writing-persistence-tests</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>writing-persistence-tests</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Main Class
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class WritingPersistenceTestsApplication {
public static void main(String[] args) {
SpringApplication.run(WritingPersistenceTestsApplication.class, args);
}
}
The problem is that your test method is by default transactional. You can disable the transactional for this method by adding:
#Test
#Transactional(value = Transactional.TxType.NEVER)
Than you get in the second save ObjectOptimisticLockingFailureException

Spring Kafka Consumer consumed message as LinkedHashMap hence automatically converting BigDecimal to double

I am using annotation based spring kafka listener to consume the kafka messages, and code is as below
Consuming Employee Object
Class Employee{
private String name;
private String address;
private Object account;
//getters
//setters
}
Account object decides on runtime whether it's Saving Account or Current Account etc.
Class SavingAcc{
private BigDecimal balance;
}
Class CurrentAcc{
private BigDecimal balance;
private BigDecimal limit;
}
Saving & Current Account having BigDecimal Fields to store balance.
Hence while sending Employee object from Kafka producer, all the fields are correctly mapped and appears in correct format of BigDecimal, etc.
But while consuming the Employee object in another service, account object is appearing as LinkedHashMap and BigDecimal fields are converted to Double. which is causing issues.
As per my understanding, the main reason can be as
a) Declaration of account as Object type instead of specific type
b) Or the deserializer should be provided more specifically. [I have already give Employee.class as type to kafka receiver deserializer, so Employee fields are correctly mapped but account fields wrong].
#Bean
public ConsumerFactory<String, Employee> consumerFactory(){
return new DefaultKafkaConsumerFactory<>(consumerConfigs(), new StringDeserializer(), new JsonDeserializer<>(Employee.class));
}
Need help on how to map or how to get the account fields properly deserialize.
Use Generics and a custom JavaType method.
Class Employee<T> {
private String name;
private String address;
private T account;
//getters
//setters
}
JavaType withCurrent = TypeFactory.defaultInstance().constructParametricType(Employee.class, CurrentAcc.class);
JavaType withSaving = TypeFactory.defaultInstance().constructParametricType(Employee.class, SavingAcc.class);
public static JavaType determineType(String topic, byte[] data, Headers headers) {
// If it's a current account
return withCurrent;
// else
return withSaving;
}
If you construct the deserializer yourself use
deser.setTypeResolver(MyClass::determineType);
When configuring with properties.
spring.json.value.type.method=com.mycompany.MyCass.determineType
You have to inspect the data or headers (or topic) to determine which type you want.
EDIT
Here is a complete example. In this case, I pass a type hint in the Account object, but an alternative would be to set a header on the producer side.
#SpringBootApplication
public class JacksonApplication {
public static void main(String[] args) {
SpringApplication.run(JacksonApplication.class, args);
}
#Data
public static class Employee<T extends Account> {
private String name;
private T account;
}
#Data
public static abstract class Account {
private final String type;
protected Account(String type) {
this.type = type;
}
}
#Data
public static class CurrentAccount extends Account {
private BigDecimal balance;
private BigDecimal limit;
public CurrentAccount() {
super("C");
}
}
#Data
public static class SavingAccount extends Account {
private BigDecimal balance;
public SavingAccount() {
super("S");
}
}
#KafkaListener(id = "empListener", topics = "employees")
public void listen(Employee<Account> e) {
System.out.println(e);
}
#Bean
public NewTopic topic() {
return TopicBuilder.name("employees").partitions(1).replicas(1).build();
}
#Bean
public ApplicationRunner runner(KafkaTemplate<String, Employee> template) {
return args -> {
Employee<CurrentAccount> emp1 = new Employee<>();
emp1.setName("someOneWithACurrentAccount");
CurrentAccount currentAccount = new CurrentAccount();
currentAccount.setBalance(BigDecimal.ONE);
currentAccount.setLimit(BigDecimal.TEN);
emp1.setAccount(currentAccount);
template.send("employees", emp1);
Employee<SavingAccount> emp2 = new Employee<>();
emp2.setName("someOneWithASavingAccount");
SavingAccount savingAccount = new SavingAccount();
savingAccount.setBalance(BigDecimal.ONE);
emp2.setAccount(savingAccount);
template.send("employees", emp2);
};
}
private static final JavaType withCurrent = TypeFactory.defaultInstance()
.constructParametricType(Employee.class, CurrentAccount.class);
private static final JavaType withSaving = TypeFactory.defaultInstance()
.constructParametricType(Employee.class, SavingAccount.class);
public static JavaType determineType(String topic, byte[] data, Headers headers) throws IOException {
if (JsonPath.read(new ByteArrayInputStream(data), "$.account.type").equals("C")) {
return withCurrent;
}
else {
return withSaving;
}
}
}
spring.kafka.consumer.auto-offset-reset=earliest
spring.kafka.producer.value-serializer=org.springframework.kafka.support.serializer.JsonSerializer
spring.kafka.consumer.value-deserializer=org.springframework.kafka.support.serializer.JsonDeserializer
spring.kafka.consumer.properties.spring.json.value.type.method=com.example.demo.JacksonApplication.determineType
Result
JacksonApplication.Employee(name=someOneWithACurrentAccount, account=JacksonApplication.CurrentAccount(balance=1, limit=10))
JacksonApplication.Employee(name=someOneWithASavingAccount, account=JacksonApplication.SavingAccount(balance=1))
POM
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>jackson</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
EDIT2
And here is an example that conveys the type hint in a header instead...
#SpringBootApplication
public class JacksonApplication {
public static void main(String[] args) {
SpringApplication.run(JacksonApplication.class, args);
}
#Data
public static class Employee<T extends Account> {
private String name;
private T account;
}
#Data
public static abstract class Account {
}
#Data
public static class CurrentAccount extends Account {
private BigDecimal balance;
private BigDecimal limit;
}
#Data
public static class SavingAccount extends Account {
private BigDecimal balance;
}
#KafkaListener(id = "empListener", topics = "employees")
public void listen(Employee<Account> e) {
System.out.println(e);
}
#Bean
public NewTopic topic() {
return TopicBuilder.name("employees").partitions(1).replicas(1).build();
}
#Bean
public ApplicationRunner runner(KafkaTemplate<String, Employee> template) {
return args -> {
Employee<CurrentAccount> emp1 = new Employee<>();
emp1.setName("someOneWithACurrentAccount");
CurrentAccount currentAccount = new CurrentAccount();
currentAccount.setBalance(BigDecimal.ONE);
currentAccount.setLimit(BigDecimal.TEN);
emp1.setAccount(currentAccount);
template.send("employees", emp1);
Employee<SavingAccount> emp2 = new Employee<>();
emp2.setName("someOneWithASavingAccount");
SavingAccount savingAccount = new SavingAccount();
savingAccount.setBalance(BigDecimal.ONE);
emp2.setAccount(savingAccount);
template.send("employees", emp2);
};
}
private static final JavaType withCurrent = TypeFactory.defaultInstance()
.constructParametricType(Employee.class, CurrentAccount.class);
private static final JavaType withSaving = TypeFactory.defaultInstance()
.constructParametricType(Employee.class, SavingAccount.class);
public static JavaType determineType(String topic, byte[] data, Headers headers) throws IOException {
if (headers.lastHeader("accountType").value()[0] == 'C') {
return withCurrent;
}
else {
return withSaving;
}
}
public static class MySerializer extends JsonSerializer<Employee<?>> {
#Override
public byte[] serialize(String topic, Headers headers, Employee<?> emp) {
headers.add(new RecordHeader("accountType",
new byte[] { (byte) (emp.getAccount() instanceof CurrentAccount ? 'C' : 'S')}));
return super.serialize(topic, headers, emp);
}
}
}
spring.kafka.consumer.auto-offset-reset=earliest
spring.kafka.producer.value-serializer=com.example.demo2.JacksonApplication.MySerializer
spring.kafka.consumer.value-deserializer=org.springframework.kafka.support.serializer.JsonDeserializer
spring.kafka.consumer.properties.spring.json.value.type.method=com.example.demo2.JacksonApplication.determineType
This annotation solved my problem
#JsonTypeInfo(use = JsonTypeInfo.Id.CLASS,include = JsonTypeInfo.As.PROPERTY,property = "#class")
private T account
it binds defined class for generic to the field

How to generate json by using lombok+gson using builder() method?

I have a json like this, how can I generate it by using lombok expression + gson library? It has a mixture of array and list. Is there any readymade tool available?
{
"transactions": [
{
"transactionIds": 123456,
"test": 3000,
"amount": {
"currency": "USD",
"value": 10
}
}
]
}
Define the values like you always do and rather generating the getters / setters you would be adding the #Data attribute, Complete code below along with the dependencies
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.ArrayList;
import java.util.List;
import lombok.Data;
public class Stack32 {
public static #Data class Amount {
private String currency;
private int value;
}
public static #Data class Child {
private int transactionIds;
private int test;
private Amount amount;
}
public static #Data class Parent {
private List<Child> transactions = new ArrayList<Child>();
}
public static void main(String[] args) throws JsonProcessingException {
Amount a1 = new Amount();
a1.setCurrency("USD");
a1.setValue(10);
Child a2 = new Child();
a2.setTransactionIds(123456);
a2.setTest(3000);
a2.setAmount(a1);
Parent a3 = new Parent();
a3.getTransactions().add(a2);
ObjectMapper mapper = new ObjectMapper();
String payload = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(a3);
System.out.println(payload);
}
}
Depdendencies :
<dependencies>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.11.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.11.0</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.6</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<scope>provided</scope>
</dependency>
</dependencies>

Writing to Dynamo table works fine, but reading throws DynamoDBMappingException

Executing orderRequestDao.save(new OrderRequest("5000", "body")); successfully places a record in Dynamo. Any attempts to read returns:
[Request processing failed; nested exception is com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMappingException:
could not invoke null on class
com.cfa.fulfillmentApi.model.OrderRequest
with value 100 of type class java.lang.String] with root cause
(Record with id: 100 exists)
I'm using the following jars (aws.sdk.version: 1.11.86):
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk</artifactId>
<version>${aws.sdk.version}</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-core</artifactId>
<version>${aws.sdk.version}</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-dynamodb</artifactId>
<version>${aws.sdk.version}</version>
</dependency>
<dependency>
<groupId>com.github.derjust</groupId>
<artifactId>spring-data-dynamodb</artifactId>
<version>4.4.1</version>
</dependency>
DyamoDb config:
Primary partition key: id (String)
Dao:
#EnableScan
public interface OrderRequestDao extends CrudRepository<OrderRequest, String> {
OrderRequest findOne(String s);
OrderRequest save(OrderRequest or);
}
Domain object:
#DynamoDBTable(tableName = "dev_transx")
public class OrderRequest {
private String id;
private String body;
public OrderRequest(String id, String body) {
this.id = id;
this.body = body;
}
public OrderRequest() {}
#DynamoDBHashKey
public String getId()
{
return id;
}
#DynamoDBAttribute
public String getBody()
{
return body;
}
public void setBody(String body) {
this.body = body;
}
#Override
public String toString() {
return String.format(
"Customer[id=%d, body='%s']",
id, body);
}
#Override
public int hashCode() {
return id.hashCode();
}
}
I've tried just about every data type for id in the domain class, but no luck.
I removed aws-java-sdk-dynamodb since it was already in spring-data-dynamodb
Most importantly I added a setter for ID in the domain class.
Adding a setter method for the field works like a charm

java.lang.NoClassDefFoundError: Lorg/apache/myfaces/custom/fileupload/UploadedFile

I want to upload files and show them in jsf page, for that I'm using tomahawk 1.1.12, jsf 2.0 and jpa 2, I'm following The BalusC tutorial but the project connot deploy and gives the error : java.lang.NoClassDefFoundError: Lorg/apache/myfaces/custom/fileupload/UploadedFile
pom.xml :
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>maven.test</groupId>
<artifactId>mavenTest</artifactId>
<version>0.0.1-SNAPSHOT</version>
<repositories>
<repository>
<id>oss.sonatype.org</id>
<name>OSS Sonatype Staging</name>
<url>https://oss.sonatype.org/content/groups/staging</url>
</repository>
<repository>
<id>prime-repo</id>
<name>PrimeFaces Maven Repository</name>
<url>http://repository.primefaces.org</url>
<layout>default</layout>
</repository>
<repository>
<id>central</id>
<name>Central Repository</name>
<url>http://repo.maven.apache.org/maven2</url>
<layout>default</layout>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>apache-maven-snapshots</id>
<url>
http://people.apache.org/repo/m2-snapshot-repository
</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>myfaces-staging</id>
<url>
http://people.apache.org/builds/myfaces/m2-staging-repository
</url>
<releases>
<enabled>false</enabled>
<!--
Enable to test a MyFaces core release candidate with tomahawk
-->
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>eclipselink</artifactId>
<version>2.5.0-RC1</version>
<exclusions>
<exclusion>
<groupId>org.eclipse.persistence</groupId>
<artifactId>commonj.sdo</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-impl</artifactId>
<version>2.1.11</version>
</dependency>
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-api</artifactId>
<version>2.1.11</version>
</dependency>
<dependency>
<groupId>postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>9.1-901.jdbc4</version>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
</dependency>
<dependency>
<groupId>org.apache.myfaces.tomahawk</groupId>
<artifactId>tomahawk</artifactId>
<version>1.1.12</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>
<!-- <dependency>
<groupId>org.apache.myfaces.core</groupId>
<artifactId>myfaces-api</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>org.apache.myfaces.tomahawk</groupId>
<artifactId>tomahawk</artifactId>
<version>1.1.14</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.9</version>
</dependency>-->
</dependencies>
</project>
my managed bean :
package mbeans;
//import java.io.IOException;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import javax.faces.application.FacesMessage;
//import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.context.FacesContext;
import javax.servlet.http.Part;
/*
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
//import org.apache.commons.el.Logger;
//import org.apache.log4j.*;
//import org.apache.log4j.spi.LoggerFactory;
*/
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.myfaces.custom.fileupload.UploadedFile;
import daoImpl.DocDAO;
import entities.Document;
//import org.slf4j.*;
#ManagedBean
#RequestScoped
public class DocBean {
public DocDAO docDAO;
private Part file;
private String titreDocument;
private String descriptionDocument;
private String lien;
private String dateMise;
private String Categorie;
private Integer sizeDocument;
private String sousCategorie;
public DocBean(){
docDAO=new DocDAO();
}
private UploadedFile uploadedFile;
private String fileName;
// Actions ------------------------------------------------------------------------------------
public void submit() {
// Just to demonstrate what information you can get from the uploaded file.
System.out.println("File type: " + uploadedFile.getContentType());
System.out.println("File name: " + uploadedFile.getName());
System.out.println("File size: " + uploadedFile.getSize() + " bytes");
// Prepare filename prefix and suffix for an unique filename in upload folder.
String prefix = FilenameUtils.getBaseName(uploadedFile.getName());
String suffix = FilenameUtils.getExtension(uploadedFile.getName());
// Prepare file and outputstream.
File file = null;
OutputStream output = null;
try {
// Create file with unique name in upload folder and write to it.
file = File.createTempFile(prefix + "_", "." + suffix, new File("c:/data"));
output = new FileOutputStream(file);
IOUtils.copy(uploadedFile.getInputStream(), output);
fileName = file.getName();
// Show succes message.
FacesContext.getCurrentInstance().addMessage("uploadForm", new FacesMessage(
FacesMessage.SEVERITY_INFO, "File upload succeed!", null));
} catch (IOException e) {
// Cleanup.
if (file != null) file.delete();
// Show error message.
FacesContext.getCurrentInstance().addMessage("uploadForm", new FacesMessage(
FacesMessage.SEVERITY_ERROR, "File upload failed with I/O error.", null));
// Always log stacktraces (with a real logger).
e.printStackTrace();
} finally {
IOUtils.closeQuietly(output);
}
}
// Getters ------------------------------------------------------------------------------------
public UploadedFile getUploadedFile() {
return uploadedFile;
}
public String getFileName() {
return fileName;
}
// Setters ------------------------------------------------------------------------------------
public void setUploadedFile(UploadedFile uploadedFile) {
this.uploadedFile = uploadedFile;
}
//#EJB
//private DocDAO fileUploaderEJB;
//private final static Logger logger = LoggerFactory.getLogger(DocDAO.class);
//public void handleFileUpload(FileUploadEvent event) {
/* titreDocument = event.getFile().getFileName();
//String contentType = event.getFile().getContentType();
byte[] bytes = event.getFile().getContents();
Document garbage = new Document();
garbage.setDescriptionDocument(titreDocument);
garbage.setFile(bytes);
garbage.setDescriptionDocument("info about the file");
fileUploaderEJB.uploadGarbage(garbage);
//((Log) logger).info("Uploaded: {}");
FacesMessage msg = new FacesMessage("Succesful", event.getFile()
.getFileName() + " is uploaded.");
FacesContext.getCurrentInstance().addMessage(null, msg);*/
//}
public String upload() throws IOException{
file.write("C:\\data\\"+getFilename(file));
return"succes";
}
private static String getFilename(Part part){
for(String cd: part.getHeader("content-disposition").split(";")){
if(cd.trim().startsWith("filename")){
String filename=cd.substring(cd.indexOf('=') + 1).trim().replace("\"", "");
return filename.substring(filename.lastIndexOf('/') + 1).substring(filename.lastIndexOf('\\') + 1);
}
}
return null;
}
/*public List<Document> getAlldoc(){
return docDAO.getAllDoc();
}
public String createdoc(){
docDAO.createDoc(titreDocument, descriptionDocument, sousCategorie, Categorie, sizeDocument, dateMise, lien);;
sizeDocument=null;
titreDocument="";
descriptionDocument="";
lien="";
sousCategorie="";
dateMise="";
Categorie="";
return "success";
}*/
public String getSousCategorie() {
return sousCategorie;
}
public void setSousCategorie(String sousCategorie) {
this.sousCategorie = sousCategorie;
}
public String getTitreDocument() {
return titreDocument;
}
public void setTitreDocument(String titreDocument) {
this.titreDocument = titreDocument;
}
public String getDescriptionDocument() {
return descriptionDocument;
}
public void setDescriptionDocument(String descriptionDocument) {
this.descriptionDocument = descriptionDocument;
}
public String getDateMise() {
return dateMise;
}
public void setDateMise(String dateMise) {
this.dateMise = dateMise;
}
public String getCategorie() {
return Categorie;
}
public void setCategorie(String categorie) {
Categorie = categorie;
}
public Integer getSizeDocument() {
return sizeDocument;
}
public void setSizeDocument(Integer sizeDocument) {
this.sizeDocument = sizeDocument;
}
public String getLien() {
return lien;
}
public void setLien(String lien) {
this.lien = lien;
}
public Part getFile() {
return file;
}
public void setFile(Part file) {
this.file = file;
}
}
my entity :
package entities;
import java.io.Serializable;
import javax.persistence.*;
/**
* The persistent class for the document database table.
*
*/
#Entity
#Table(name="document")
#NamedQuery(name="Document.findAll", query="SELECT d FROM Document d")
public class Document {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name="\"idDocument\"", unique=true, nullable=false)
private Integer idDocument;
#Column(length=45)
private String categorie;
#Column(name="\"dateMise\"", length=45)
private String dateMise;
#Column(name="\"descriptionDocument\"", length=60)
private String descriptionDocument;
#Lob
#Column
private byte[] file;
#Column(length=45)
private String lien;
#Column(name="\"sizeDocument\"")
private Integer sizeDocument;
#Column(name="\"sousCategorie\"", length=45)
private String sousCategorie;
#Column(name="\"titreDocument\"", length=45)
private String titreDocument;
public Document() {
}
public Integer getIdDocument() {
return this.idDocument;
}
public void setIdDocument(Integer idDocument) {
this.idDocument = idDocument;
}
public String getCategorie() {
return this.categorie;
}
public void setCategorie(String categorie) {
this.categorie = categorie;
}
public String getDateMise() {
return this.dateMise;
}
public void setDateMise(String dateMise) {
this.dateMise = dateMise;
}
public String getDescriptionDocument() {
return this.descriptionDocument;
}
public void setDescriptionDocument(String descriptionDocument) {
this.descriptionDocument = descriptionDocument;
}
public byte[] getFile() {
return this.file;
}
public void setFile(byte[] file) {
this.file = file;
}
public String getLien() {
return this.lien;
}
public void setLien(String lien) {
this.lien = lien;
}
public Integer getSizeDocument() {
return this.sizeDocument;
}
public void setSizeDocument(Integer sizeDocument) {
this.sizeDocument = sizeDocument;
}
public String getSousCategorie() {
return this.sousCategorie;
}
public void setSousCategorie(String sousCategorie) {
this.sousCategorie = sousCategorie;
}
public String getTitreDocument() {
return this.titreDocument;
}
public void setTitreDocument(String titreDocument) {
this.titreDocument = titreDocument;
}
}
and my web page xhtml:
<h:panelGrid columns="3">
<h:outputLabel for="file" value="Select file" />
<t:inputFileUpload id="file" value="#{docBean.uploadedFile}" required="true" />
<h:message for="file" style="color: red;" />
<h:panelGroup />
<h:commandButton value="Submit" action="#{docBean.submit}" />
<h:message for="uploadForm" infoStyle="color: green;" errorStyle="color: red;" />
</h:panelGrid>
</h:form>
<h:outputLink value="file/#{docBean.fileName}" rendered="#{docBean.fileName != null}">
Download back
</h:outputLink>
any idea ?
<dependency>
<groupId>org.apache.myfaces.tomahawk</groupId>
<artifactId>tomahawk</artifactId>
<version>1.1.12</version>
</dependency>
replace with
<dependency>
<groupId>org.apache.myfaces.tomahawk</groupId>
<artifactId>tomahawk20</artifactId>
<version>1.1.12</version>
</dependency>
thanks Omar it was a matter of version I tried to upload using only jsf 2.2 with no tomahawk or primefaces.
resolved

Resources