Reputation: 31
`Issue is occurring after upgrading the orika-mapper 1.4.6 to 1.5.4
Here is the custom Mapper class with registering custom mapper for source object and destination object.'
@Component
public class CustomMapper extends ConfigurableMapper implements Imapper {
@Override
public void configure(MapperFactory mapperFactory) {
mapperFactory.registerClassMap(mapperFactory.classMap(A.class,B.class)
.byDefault().customize(getAtoBMapper()).toClassMap());
}
private CustomMapper<A,B> getAtoBMapper() {
return new CustomMapper<A,B>() {
@Override
public void mapAtoB(A a,B b, MappingContext context) {
};
}
Here is caller:
MappingContext mappingContext = new MappingContext(map);
List<B>bList =
customMapper.mapAsList(aList,B.class,
mappingContext);
//aList is a list of object a
Exception occurred:
ma.glasnost.orika.MappingException: java.lang.NullPointerException
at ma.glasnost.orika.impl.generator.MapperGenerator.build(MapperGenerator.java:104) ~[orika-core-1.5.4.jar:?]
at ma.glasnost.orika.impl.DefaultMapperFactory.buildMapper(DefaultMapperFactory.java:1478) ~[orika-core-1.5.4.jar:?]
at ma.glasnost.orika.impl.DefaultMapperFactory.lookupMapper(DefaultMapperFactory.java:738) ~[orika-core-1.5.4.jar:?]
at ma.glasnost.orika.impl.MapperFacadeImpl.resolveMapper(MapperFacadeImpl.java:568) ~[orika-core-1.5.4.jar:?]
at ma.glasnost.orika.impl.MapperFacadeImpl.resolveMappingStrategy(MapperFacadeImpl.java:178) ~[orika-core-1.5.4.jar:?]
at ma.glasnost.orika.impl.DefaultBoundMapperFacade$BoundStrategyCache.getStrategy(DefaultBoundMapperFacade.java:259) ~[orika-core-1.5.4.jar:?]
at ma.glasnost.orika.impl.DefaultBoundMapperFacade.mapReverse(DefaultBoundMapperFacade.java:152) ~[orika-core-1.5.4.jar:?]
at ma.glasnost.orika.generated.Orika_B_A_Mapper113184950754086$47.mapBtoA(Orika_B_A_Mapper113184950754086$47.java) ~[orika-core-1.5.4.jar:?]
Upvotes: 3
Views: 1417
Reputation: 29
It seems Orika is abandoned and there is no fix so far. So I implemented a workaround and hope it will be useful for others facing the same issue.
We need to get a proper ma.glasnost.orika.MappingContext
created by Orika itself, so mappingContext.getProperty(Properties.CAPTURE_FIELD_CONTEXT)
is not null
. To achieve this we have to create a utility class.
package org.test;
import ma.glasnost.orika.MappingContext;
import ma.glasnost.orika.MappingContextFactory;
import ma.glasnost.orika.impl.DefaultMapperFactory;
/**
* The utility class to get {@link MappingContext} configured by Orika
* and ready to be used by {@link ma.glasnost.orika.MapperFacade#map(java.lang.Object, java.lang.Class)}.
*/
public final class MappingContextUtils {
private static final MappingContextFactory MAPPING_CONTEXT_FACTORY;
static {
MAPPING_CONTEXT_FACTORY = new CustomDefaultMapperFactory.Builder().build().getContextFactory();
}
/**
* Gets {@link MappingContext} ready to be used by {@link ma.glasnost.orika.MapperFacade#map(java.lang.Object, java.lang.Class)}.
* Manual creation of {@link MappingContext} does not work. Please see the link below.
*
* @return {@link MappingContext}
* @see <a href="https://github.com/orika-mapper/orika/issues/354">https://github.com/orika-mapper/orika/issues/354</a>
*/
public static MappingContext getMappingContext() {
return MAPPING_CONTEXT_FACTORY.getContext();
}
/**
* The custom {@link DefaultMapperFactory} to expose getter
* for {@link MappingContextFactory} so {@link MappingContext} with prefilled globalProperties can be created.
*
* @author Dmitry Lebedko ([email protected])
*/
private static class CustomDefaultMapperFactory extends DefaultMapperFactory {
/**
* Constructs a new instance of DefaultMapperFactory
*
* @param builder {@link MapperFactoryBuilder}
*/
protected CustomDefaultMapperFactory(MapperFactoryBuilder<?, ?> builder) {
super(builder);
}
/**
* Gets {@link MappingContextFactory}.
*
* @return {@link MappingContextFactory}
*/
public MappingContextFactory getContextFactory() {
return contextFactory;
}
public static class Builder extends DefaultMapperFactory.MapperFactoryBuilder<CustomDefaultMapperFactory, Builder> {
@Override
public CustomDefaultMapperFactory build() {
return new CustomDefaultMapperFactory(this);
}
@Override
protected CustomDefaultMapperFactory.Builder self() {
return this;
}
}
}
}
Now it may be used like that
MappingContext mappingContext = MappingContextUtils.getMappingContext(); // here we get a mapping context created by Orika
List bList = customMapper.mapAsList(aList, B.class, mappingContext);
Upvotes: 1