orika-mapper/orika

Null Pointer exception during mapping of complex objects

mgagauz opened this issue · 2 comments

Here is a simple application which tries to convert objects with a nesting level more than one:

public class TestApp {
	public static class ClassA {
		Map<String, String> all;
		public Map<String, String> getAll() {
			return all;
		}
		public void setAll(Map<String, String> all) {
			this.all = all;
		}
	}

	public static class ClassB {
		Map<String, String> section1;
		Map<String, String> section2;
		public Map<String, String> getSection1() {
			return section1;
		}
		public void setSection1(Map<String, String> section1) {
			this.section1 = section1;
		}
		public Map<String, String> getSection2() {
			return section2;
		}
		public void setSection2(Map<String, String> section2) {
			this.section2 = section2;
		}
	}

	public static void main(String[] args) {
		MapperFactory mapperFactory = new DefaultMapperFactory.Builder()
				.captureFieldContext(true)
				.build();
		mapperFactory.classMap(ClassA.class, ClassB.class)
				.field("all['s1prop1']", "section1['prop1']")
				.field("all['s1prop2']", "section1['prop2']")
				.field("all['s2prop1']", "section2['prop1']")
				.field("all['s2prop2']", "section2['prop2']")
				.byDefault()
				.register();
		ClassA source = new ClassA();
		source.setAll(Map.of("s1prop1", "1", "s1prop2", "2"));
		ClassB dest = mapperFactory.getMapperFacade().map(source, ClassB.class);
		System.out.println(dest.getSection1());
		System.out.println(dest.getSection2()); // Should be null
	}
}

Running it will cause NPE during conversion:

Error occurred: java.lang.NullPointerException
	at ma.glasnost.orika.impl.ExceptionUtility.newMappingException(ExceptionUtility.java:55)
	at ma.glasnost.orika.impl.MapperFacadeImpl.map(MapperFacadeImpl.java:682)
	at ma.glasnost.orika.impl.MapperFacadeImpl.map(MapperFacadeImpl.java:651)
	at TestApp.main(TestApp.java:55)
Caused by: java.lang.NullPointerException
	at ma.glasnost.orika.generated.Orika_ClassB_ClassA_Mapper821519033837200$0.mapAtoB(Orika_ClassB_ClassA_Mapper821519033837200$0.java)
	at ma.glasnost.orika.impl.mapping.strategy.UseCustomMapperStrategy.map(UseCustomMapperStrategy.java:77)
	at ma.glasnost.orika.impl.MapperFacadeImpl.map(MapperFacadeImpl.java:672)
	... 2 more

I would propose to change SourceCodeContext

 private void beginCaptureFieldContext(StringBuilder out, FieldMap fieldMap, VariableRef source, VariableRef dest) {
		out.append(format("mappingContext.beginMappingField(\"%s\", %s, %s, \"%s\", %s, %s);\n" + "try{\n",
                escapeQuotes(fieldMap.getSource().getExpression()), usedType(fieldMap.getAType()), source.asWrapper(),
				escapeQuotes(fieldMap.getDestination().getExpression()), usedType(fieldMap.getBType()), dest.asWrapper()));
    }

to

 private void beginCaptureFieldContext(StringBuilder out, FieldMap fieldMap, VariableRef source, VariableRef dest) {
		out.append(format("mappingContext.beginMappingField(\"%s\", %s, %s, \"%s\", %s, %s %s %s %s);\n" + "try{\n",
                escapeQuotes(fieldMap.getSource().getExpression()), usedType(fieldMap.getAType()), source.asWrapper(),
				escapeQuotes(fieldMap.getDestination().getExpression()), usedType(fieldMap.getBType()),
				dest.pathNotNull(), " ? ", dest.asWrapper(), " : null"));
    }