An exception of using dozer to copy data from map to java bean - dozer

I want to copy data from map(request.getParameterMap()) to java bean. For example:
Map<String,Object> map = new HashMap<>();
map.put("payment_code", "1420956468542a2");
//...
public class PaymentLogDTO {
#Mapping("payment_code")
private String paymentCode;
//...
}
but when I execute map method in unit test,
DozerBeanMapper dozer = new DozerBeanMapper();
dozer.map(map, PaymentLogDTO.class);
it failed. The exception message is:
org.dozer.MappingException: No such field found java.util.HashMap.payment_code
at org.dozer.util.ReflectionUtils.getFieldFromBean(ReflectionUtils.java:322)
at org.dozer.util.ReflectionUtils.getFieldFromBean(ReflectionUtils.java:320)
at org.dozer.util.ReflectionUtils.getFieldFromBean(ReflectionUtils.java:320)
at org.dozer.util.ReflectionUtils.getFieldFromBean(ReflectionUtils.java:309)
at org.dozer.propertydescriptor.FieldPropertyDescriptor$ChainedPropertyDescriptor.<init>(FieldPropertyDescriptor.java:104)
at org.dozer.propertydescriptor.FieldPropertyDescriptor.<init>(FieldPropertyDescriptor.java:51)
at org.dozer.propertydescriptor.PropertyDescriptorFactory.getPropertyDescriptor(PropertyDescriptorFactory.java:64)
at org.dozer.fieldmap.FieldMap.getSrcPropertyDescriptor(FieldMap.java:385)
at org.dozer.fieldmap.FieldMap.getSrcFieldValue(FieldMap.java:86)
at org.dozer.MappingProcessor.mapField(MappingProcessor.java:294)
at org.dozer.MappingProcessor.map(MappingProcessor.java:267)
at org.dozer.MappingProcessor.mapToDestObject(MappingProcessor.java:216)
at org.dozer.MappingProcessor.createByCreationDirectiveAndMap(MappingProcessor.java:196)
at org.dozer.MappingProcessor.mapGeneral(MappingProcessor.java:170)
at org.dozer.MappingProcessor.map(MappingProcessor.java:104)
at org.dozer.MappingProcessor.map(MappingProcessor.java:99)
at org.dozer.DozerBeanMapper.map(DozerBeanMapper.java:120)
at org.springside.modules.mapper.BeanMapper.map(BeanMapper.java:36)
Is there any method can solve this problem? That is I don't need to create a java bean using the same name of query paramter name as it's properties' names.

The #Mapping annotation tells the source/destination field, it has nothing related to the Map class...
So with #Mapping("payment_code"), it looks for a field "payement_code", and not for an element in your map collection.

Related

Exception when using a #ResultSetMapping on a native SQL query with a Spring Data JPA Repository?

I'm currently building a native SQL query with Spring Data JPA that uses a #SqlResultSetMapping. The query looks filters the rows based on certain parameters and then returns all of the columns of an entity table plus additionally it calculates another column on the fly. Something like this:
#Entity
#NamedNativeQuery(
name = "Entity.searchBySearchParams",
resultSetMapping = "SearchResultMapping",
query = "select entity.*, (*calculation*) as anotherField from ..."
)
#SqlResultSetMapping(
name = "SearchResultMapping",
entities = #EntityResult(entityClass = Entity.class),
columns = #ColumnResult(name = "anotherField", type = double.class)
)
public class Entity { ... }
And then I'm trying to call this native, named query from my repository (which extends JpaRepository<T, Long>) like that:
#Query(nativeQuery = true, name = "Entity.searchBySearchParams")
List<Object[]> searchBySearchParams( ... lots of params ... );
Where I'm expecting searchBySearchParams(...)[0] to be of type Entity and searchBySearchParams(...)[1] of type Double.
Unfortunately I'm getting this exception when trying to call the above repository method:
org.springframework.dao.InvalidDataAccessApiUsageException: Cannot create TypedQuery for query with more than one return; nested exception is java.lang.IllegalArgumentException: Cannot create TypedQuery for query with more than one return
at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:374)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:257)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:528)
at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61)
at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:242)
....
Which is weird since calling the query and applying my result set mapping directly by invoking the EntityManage#createNamedQuery method worked perfectly fine.
Am I missing something or should I post this to the Spring Data Jira? Neither JPA's nor Spring's documentation provided information for my case ...
More Background Info:
Actually the additional column anotherField is a transitive property on my Entity. I haven't found a way of mapping that column to the transitive property, which is why my repository method currently returns Object[].

How to skip calling the getter method when the lazy field was not loaded in mapstruct to avoid LazyInitializationException?

How to skip calling the getter method when the lazy field was not loaded in mapstruct mapper that map JPA entity to DTO?
I am using JPA EntityGraph to load required child entity for method1 but method2 I am using different EntityGraph and I don't want to create different mapper for every case.
Is there any way to create one mapper for both methods and ignore property that lazy loaded?
you can have two method who make the same mapping, and one where you ignore field that are not initialized
abstract Personne toDtoV1(PersonneModel model);
#Mapping(target = "nom", ignore = true)
abstract Personne toDtoV2(PersonneModel model);
or if you need only one methode, you create a mapping with all field who can be lazy loaded in ignore, and in a methode after mapping you check if relation is loaded and you make the mapping yourself
#Mapping(target = "nom", ignore = true)
abstract Personne toDtoV2(PersonneModel model);
#AfterMapping
void afterpersonneModel(PersonneModel dto, #MappingTarget Personne mode){
//check if relation is loaded
///and make the mapping
}

Map Target object with no source object using MapStruct

I want to map a Target object with no source object using MapStruct. I tried it, but getting the below error.
Can't generate mapping method with no input arguments
Mapper code
public interface MyMapper {
#Mapping(target="student.courseName", constant="Master in Science")
Target map();
}
As you can see this is not supported. And why would you do that? Why not just write your own method?
That aside, you can theoretically try passing a dummy parameter that won't be mapped.
public interface MyMapper {
#Mapping(target="student.courseName", constant="Master in Science")
Target map(Integer dummy);
}

GWT: com.google.gwt.user.client.rpc.SerializationException for Type 'java.util.HashMap$KeySet'

I am getting com.google.gwt.user.client.rpc.SerializationException exception for HashSet.
Initially I thought either HashSet of Long is not supported.
But https://developers.google.com/web-toolkit/doc/latest/RefJreEmulation contains both of these.
What would be the problem?
I am posting the Service method here:
public Set<Long> getNamesFromIDs(Set<Long> ids) {
return manager.getNamesFromIDs(ids);
}
Here, manager is the reference to the Manager class which is included from a library.
I am posting the manager method too:
public Set<Long> getNamesFromIDs(Set<Long> styleIds) {
List<Long> listIDs = new ArrayList<Long>(styleIds);
Map<Long, Discount> personMap = personDAO.getStyleIdToDiscountMap(listIDs, 0);
return personMap.keySet();
}
Detailed Exception Message:
com.google.gwt.user.client.rpc.SerializationException: Type 'java.util.HashMap$KeySet'
was not included in the set of types which can be serialized by this
SerializationPolicy or its Class object could not be loaded.
For security purposes, this type will not be serialized.: instance = [30002, 30001]
The above classes from java.util are serialized by the custom field serializer.
Serialization for the KeySet is not supported by GWT. It does not implement a Serializable interface ( so it is not serializable in java world either)

JAXB How to force xsi:type in array of subclasses? (JBoss 4.2.3)

(Please note; i'm completely new to webservices, so the following may be stupid/incorrect but please be patient)
In my WebServices' #WebMethod I'm returning an array of an abstract base class (JAXB annotated entities in JBoss 4.2.3).
Obviously unless the type information is encoded per array element this will fail...
So how do I ensure that JAXB adds the xsi:type attribute?
My WebService interface has the following annotation, and I've tried every legal combination:
#SOAPBinding(style = RPC, parameterStyle = WRAPPED, use = LITERAL)
the methods on this interface take x2 parameters annotated #WebParam(name="...", mode=IN)
Other methods with similar signatures that don't return a heterogeneous array work perfectly.
Some related things:
Looks like JBoss uses the types defined in the method signatures to decide what classes to load into the JAXBContext - if I change the return types to Object[] it throws an error stating that the AbstractBase class "nor any of its super class is known to this context." I've added dummy methods returning the specific subclasses so that the generated WSDL has a list of all of them.
when I try to write tests for this, all is ok for single elements, but JAXB throws an error for array types: unable to marshal type "[LAbstractBase;" as an element because it is missing an #XmlRootElement annotation
From code like that shown below (note: AbstractBase, ConcreteOne and ConcreteTwo all have #XmlRootElement annotations)
private static final Class<?>[] CLASSES_TO_BE_BOUND = new Class<?>[]{
//Note; adding AbstractBase[].class doesn't work either
AbstractBase.class, ConcreteOne.class, ConcreteTwo.class
};
#Test
public void testXsiTypeAttributeIsIncludedInHeterogeneousArray()
{
AbstractBase[] array = new AbstractBase[2];
array[0] = new ConcreteOne();
array[1] = new ConcreteTwo();
Marshaller marshaller = createMarshaller();
StringWriter sw = new StringWriter();
marshaller.marshal(array, sw);
String output = sw.toString();
Assert.assertTrue(output.contains("xsi:type=\""));
}
private Marshaller createMarshaller() throws Exception {
JAXBContext context = JAXBContext.newInstance(CLASSES_TO_BE_BOUND);
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
return marshaller;
}
Ideally I'd like to be able to test some bits relating to arrays, but it's far more critical that I can get the type information encoded per element in the JBoss environment.
Edit: Own Answer
JBoss (4.2.3) is doing something clever, but not too clever - it will handle the returning of arrays but not polymorphic arrays. This threw me a bit as I tried to get this way of doing it working in my tests.
Instead of trying to solve the JBoss WebService issue I made my tests more comprehensive - making the array a member of a simple container class and then annotating the array's getter with:
#XmlElementRefs({
#XmlElementRef(type = ConcreteOne.class),
#XmlElementRef(type = ConcreteTwo.class)
})
public AbstractBase[] getItems() { /*...*/ }
Which worked, and returning this in the JBoss WebService also worked! Though I'm using:
#SOAPBinding(style = DOCUMENT, parameterStyle = BARE, use = LITERAL)
So it's not adding the xsi:type attribute, but document nodes are correctly tagged:
<ConcreteOne>...</ConcreteOne>
At some point I'll change the WebService to use RPC as I don't really like the single argument restriction, but for now this is working fine.