Value 0 of type class java.util.LinkedHashMap does not correspond to any CQL3 type - cassandra

I'm trying to save a spring entity to Cassandra (2.0.11) using a Cassandra repository. The entity class is as follows:
#Table(value="gs")
public class GsJsonStore implements Serializable {
private static final long serialVersionUID = 7133072282172062535L;
#PrimaryKey
private String id;
#Column(value = "object")
#CassandraType(type=DataType.Name.MAP)
private Map<String, String> _object;
#Column(value = "subject")
private String _subject;
//Getter and Setter methods.
}
The code I'm using to save the object:
GsJsonStore gsJsonStore = new GsJsonStore();
gsJsonStore.setPredicate("Predicate");
gsJsonStore.setSubject("Subject");
gsJsonStore.setObject(jsonToMap(jsonNode));
repository.save(gsJsonStore);
The jsonToMap function:
public Map<String,String> jsonToMap(JsonNode json) {
ObjectMapper mapper = new ObjectMapper();
Map<String, String> result = mapper.convertValue(json, Map.class);
return result;
}
I get the following error while storing the object:
java.lang.IllegalArgumentException:
Value 0 of type class java.util.LinkedHashMap does not correspond to any CQL3 type
Where am I going wrong?

Related

ModelMapper failed to convert java.lang.String to java.lang.Long

I have rest models that I use to build JSON that I send.
A rest model
#Getter #Setter
#ToString
public class OrderRequestModel {
private String orderKeyId;
private String paymentMode;
private double totalAmount;
private List<ProductRequestModel> orderProducts;
private UserDetailsRequestModel seller;
private Date createdAt;
}
The ProductRequestModel is similar
#Getter #Setter
#ToString
public class ProductRequestModel {
private String productKeyId;
private String name;
private double price;
private int qty;
private String imgPath;
private CategoryRequestModel category;
}
I'm passing the models to a DTO layer which is in relation with database (they include a long Id):
#Getter #Setter
#ToString
public class OrderDto implements Serializable {
#Getter(AccessLevel.NONE)
#Setter(AccessLevel.NONE)
private static final long serialVersionUID = 1L;
private Long id;
private String orderKeyId;
private String paymentMode;
private double totalAmount;
private List<ProductDto> orderProducts;
private UserDto seller;
private Date createdAt;
}
And my ProductDto :
#Getter #Setter
#ToString
public class ProductDto implements Serializable {
// ommit this member and do not generate getter / setter
#Getter(AccessLevel.NONE)
#Setter(AccessLevel.NONE)
private static final long serialVersionUID = 1L;
private Long id;
private String productKeyId;
private String name;
private double price;
private int qty;
private String imgPath;
private CategoryDto category = new CategoryDto();
}
When i try to map OrderDto with the associated model i do it implicitelly :
OrderDto orderDto = modelMapper.map(orderRequestModel, OrderDto.class);
In theory, orderKeyId from the model should match with its equivalent in the Dto. Unfortunatelly It returns an error :
Converter org.modelmapper.internal.converter.NumberConverter#3e36f4cc failed to convert java.lang.String to java.lang.Long.
Caused by: org.modelmapper.MappingException: ModelMapper mapping errors:
I do need the Id in the DTO because if i want to make an update I do use "id"
This issue is caused because of the Mapping Strategies. We can set the Mapping Strategies to STRICT so that when mapping from source object property to target object's property it only maps only those property which are perfectly matching in property name as well as it's data type. Below is an example.
public ModelMapper modelMapper() {
ModelMapper modelMapper = new ModelMapper();
modelMapper.getConfiguration()
.setMatchingStrategy(MatchingStrategies.STRICT);
}
FYI:
http://modelmapper.org/user-manual/configuration/#matching-strategies

JHipster EntityMapper interface (mapstruct): map a Spring projection interface

I've generated a new project with JHipster v4.6.0 generator and I'm using its EntityMapper interface to do the mapping between domain and DTO objects.
public interface EntityMapper <D, E> {
public E toEntity(D dto);
public D toDto(E entity);
public List <E> toEntity(List<D> dtoList);
public List <D> toDto(List<E> entityList);
}
I need to use the Spring projection to have a smaller domain and DTO objects, (I don't want all fields of the entity), so I've created an interface with only the getters of the fields I need, and I've created a method in the repository which retrive this interface type (following the Spring reference guide)
public interface ClienteIdENome {
Long getId();
String getNome();
}
#Repository
public interface ClienteRepository extends JpaRepository<Cliente,Long> {
ClienteIdENome findById(Long id);
}
The query findById retrieve a ClienteIdENome object with only id and nome fields.
Now, I would like to map this object in the following DTO:
public class ClienteIdENomeDTO implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
#NotNull
#Size(max = 50)
private String nome;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
}
So, I created the mapper interface:
#Mapper(componentModel = "spring", uses = {})
public interface ClienteIdENomeMapper extends EntityMapper<ClienteIdENomeDTO, ClienteIdENome> {
}
But Eclipse report to me an error in the EntityMapper interface for the method "public E toEntity(D dto)" with the message:
No implementation type is registered for return type it.andrea.ztest01.repository.ClienteIdENome.
Any help?
Thanks a lot
Your ClienteIdENome is not really an entity. I would argue that you don't need to use the EntityMapper, but you need to define a one way mapper. From ClienteIdENome to ClienteIdENomeDTO.
Your mapper needs to look like:
public interface ClienteIdENomeMapper {
ClienteIdENomeDTO toDto(ClienteIdENome entity);
List <ClienteIdENomeDTO> toDto(List<ClienteIdENome> entityList);
}
I don't know JHipster, so I can't say what will mean using a mapper different than EntityMapper.

JAXB: using #XmlID along with Hibernate #Id

I have following hibernate property:
#Id()
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id = null;
I want to add JAXB annotation #XmlID to this id but #XmlID can only be applied to String data types. How can I solve this problem.
#XmlID
#Transient
public String getXId(){
return this.id;
}
public String setXId(String s){
this.id = Long.parseDouble(s);
}
Use #XmlJavaTypeAdapter(IDAdapter.class) along with #XmlID where IDAdapter is
import javax.xml.bind.DatatypeConverter;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class IDAdapter extends XmlAdapter<String, Long> {
#Override
public Long unmarshal(String string) throws Exception {
return DatatypeConverter.parseLong(string);
}
#Override
public String marshal(Long value) throws Exception {
return DatatypeConverter.printLong(value);
}
}

#XmlPath(".") conflicts with #XmlAdapter

having this Jaxb Xml definition, i try to remove the Map Elements Wrapper by adding #XmlPath(".") but it cause exception during the unmarchaling
#XmlRootElement
public abstract class ViewElement{
#XmlJavaTypeAdapter(value=EventAdapter.class)
public Map<Event, String> getEvents() {
}
private transient Class entityType;
public Class getEntityType() {
return entityType;
}
}
And the EventAdapter is
public class EventAdapter extends XmlAdapter<EventAdapter.AdaptedMap, Map<Event, String>> {
public static class AdaptedMap {
#XmlVariableNode("key")
List<AdaptedEntry> entries = new ArrayList<AdaptedEntry>();
}
public static class AdaptedEntry {
#XmlTransient
public String key;
#XmlValue
public String value;
}
.....
}
my output was
<element>
<events>
<onCellEdit>do some thing<onCellEdit>
</events>
<entityType>com.agitech.erp.model.erp.ErpFolder</entityType>
<element>
I try to remove the <events> tag by adding #XmlPath(".")
#XmlPath(".")
#XmlJavaTypeAdapter(value=EventAdapter.class)
public Map<Event, String> getEvents() {
}
The output is good
<element>
<onCellEdit>do some thing<onCellEdit>
<entityType>com.agitech.erp.model.erp.ErpFolder</entityType>
<element>
but the unmarchaling faileds
Caused by: Exception [EclipseLink-3002] (Eclipse Persistence Services - 2.6.0.v20140809-296a69f): org.eclipse.persistence.exceptions.ConversionException
Exception Description: The object [], of class [class java.lang.String], from mapping [org.eclipse.persistence.oxm.mappings.XMLDirectMapping[entityType-->view.entityType/text()]] with descriptor [XMLDescriptor(com.agitech.erp.view.BeanView --> [DatabaseTable(view), DatabaseTable(viewFrame), DatabaseTable(viewElement)])], could not be converted to [class java.lang.Class].
Internal Exception: java.lang.ClassNotFoundException:
at org.eclipse.persistence.exceptions.ConversionException.couldNotBeConvertedToClass(ConversionException.java:95)
at org.eclipse.persistence.internal.helper.ConversionManager.convertObjectToClass(ConversionManager.java:446)
Debuging Jaxb bring me to the line
org.eclipse.persistence.internal.oxm.XMLDirectMappingNodeValue
public void endElement(XPathFragment xPathFragment, UnmarshalRecord unmarshalRecord) {
...
line 205 unmarshalRecord.setAttributeValue(convertedValue, xmlDirectMapping);
}
During the unmarchaling of entityType value, the UnmarshalRecordImpl.currentObj contains the EventAdapter instead of the parent element
I modify org.eclipse.persistence.internal.oxm.record.UnmarshalRecordImpl
public XPathNode getNonAttributeXPathNode(String namespaceURI, String localName, String qName, Attributes attributes) {
....
if(null == resultNode && null == nonPredicateNode) {
// ANY MAPPING
resultNode = xPathNode.getAnyNode();
// by default it return the EventAdapter, changing it to NULL fix my problem
}
....
}
Not a safe solution
I have been able to reproduce the issue that you are seeing, but haven't yet worked out the cause. You can use the following bug to track the progress on this issue:
http://bugs.eclipse.org/457169
After trying a lot of things, I was able to find a workaround for this issue. I thought of posting here the same so it can be helpful to someone else in the future. The lead has confirmed the issue around 5 years ago but seems like they have not fixed it and I was facing a similar issue.
Basically, we can use the beforeMarshal and afterUnmarshal methods to change the values in the fields.
You need to create a field List<Object> with #XmlAnyElement(lax=true) along with Map<String,Object>.
Remove the #XmlPath(".") and the XMLAdapter class.
Mark the field Map<String, Object> with #XmlTransient.
Now within the beforeMarshal and afterMarshal fields, you can exchange the data. During the unmarshal in beforeunmarshal, all the unknown field values will be present within the List<Object> loop over it and add it to the Map<String, Object>.
Similarly during the marshaling, you can move the values Map<String, Object> to List<Object> by creating the DOM elements.
Marshaling all values are added to root as DOM Elements are present and during Unmarshaling known values are read first and then-unknown values are stored within List<Object> due to #XmlAnyElement.
I have created an example using the Customer class, you can modify it accordingly for your need.
#JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, visible = true, property = "isA")
#JsonInclude(Include.NON_NULL)
#JsonIgnoreProperties(ignoreUnknown = true)
#XmlRootElement(name = "Customer")
#XmlType(name = "Customer", propOrder = {"name", "age", "otherElements"})
#XmlAccessorType(XmlAccessType.FIELD)
#Getter
#Setter
#AllArgsConstructor
#ToString
#NoArgsConstructor
public class Customer {
#XmlTransient
private String isA;
private String name;
private String age;
#XmlAnyElement(lax = true)
#JsonIgnore
private List<Object> otherElements = new ArrayList<>();
#JsonIgnore
#XmlTransient
private Map<String, Object> userExtensions = new HashMap<>();
#JsonAnyGetter
#JsonSerialize(using = CustomExtensionsSerializer.class)
public Map<String, Object> getUserExtensions() {
return userExtensions;
}
#JsonAnySetter
public void setUserExtensions(String key, Object value) {
userExtensions.put(key, value);
}
private void beforeMarshal(Marshaller m) throws ParserConfigurationException {
System.out.println("Before Marshalling User Extension: " + userExtensions);
ExtensionsModifier extensionsModifier = new ExtensionsModifier();
otherElements = extensionsModifier.Marshalling(userExtensions);
System.out.println("Before Marshalling Final Other Elements " + otherElements);
userExtensions = new HashMap<>();
}
private void afterUnmarshal(Unmarshaller m, Object parent) throws ParserConfigurationException {
System.out.println("After Unmarshalling : " + otherElements);
ExtensionsModifier extensionsModifier = new ExtensionsModifier();
userExtensions = extensionsModifier.Unmarshalling(otherElements);
otherElements = new ArrayList();
}
}
You can refer the creation of DOM ELEMENTS here:https://stackoverflow.com/a/24239105/7584240
You can refer my complete answer here: https://stackoverflow.com/a/67923216/7584240

using JAXB, the XML is loaded into a class. This class is then used within another class to be marshalled out differently

Given an XML file of offerings that is then loaded into a class called Offerings via JAXB.
This class has the following:
Name, Price sub-Class, Modifiers, Ordering Rules etc.
I then create an order and within that order
Order
public class ProductOrder {
private String OrderId;
private Date createDate;
private OrderStatus orderStatus;
private int CustomerOrderID;
private ArrayList<ProductOrderItem> productOrderItems = new ArrayList<ProductOrderItem>();
}
Order Item
public class ProductOrderItem {
private int OrderItemID;
private **Offering** offering;
private Map<String, Integer> qtylist = new HashMap<String, Integer>();
private ArrayList<Modifier> modifiers = new ArrayList<Modifier>();
private int qty;
}
Offering
#XmlRootElement(name = "offering")
#XmlAccessorType(XmlAccessType.FIELD) // NONE)
public class Offering {
#XmlAttribute
private String id;
#XmlElement
private String offeringName;
#XmlElement
private String description;
#XmlElement
private Integer price;
}
The Offering and Modifiers are classes with JAXB already which I only want to push part of the XML. How would I change the anotations such that only part of the elements are sent? For example not the offering -> modifiers?
Use #XmlTransient instead of the #XmlElement tag.

Resources