Skip to content

Commit ccb55b0

Browse files
Adonis Charalambidisgarethahealy
authored andcommitted
[ISSUE: 696] fixes nested proto3 messages ClassNotFoundException (#697)
* fixes nested proto3 messages ClassNotFoundException * proto3 msg container names in reverse order. * missing license header
1 parent d68728c commit ccb55b0

5 files changed

Lines changed: 152 additions & 7 deletions

File tree

dozer-integrations/dozer-proto3/src/main/java/com/github/dozermapper/protobuf/util/ProtoUtils.java

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import java.lang.reflect.Method;
2020
import java.util.ArrayList;
2121
import java.util.Collection;
22+
import java.util.LinkedList;
2223
import java.util.List;
2324
import java.util.Map;
2425

@@ -27,7 +28,7 @@
2728
import com.github.dozermapper.core.util.MappingUtils;
2829
import com.google.common.base.CaseFormat;
2930
import com.google.protobuf.ByteString;
30-
import com.google.protobuf.DescriptorProtos;
31+
import com.google.protobuf.DescriptorProtos.FileOptions;
3132
import com.google.protobuf.Descriptors;
3233
import com.google.protobuf.Message;
3334
import com.google.protobuf.ProtocolMessageEnum;
@@ -207,23 +208,33 @@ private static Class<?> getJavaClassIgnoreRepeated(final Descriptors.FieldDescri
207208
return getEnumClassByEnumDescriptor(descriptor.getEnumType(), beanContainer);
208209
case MESSAGE:
209210
return MappingUtils.loadClass(StringUtils.join(
210-
getFullyQualifiedClassName(descriptor.getMessageType().getFile().getOptions(), descriptor.getMessageType().getName()), '.'), beanContainer);
211+
getFullyQualifiedClassName(descriptor.getMessageType().getContainingType(),
212+
descriptor.getMessageType().getFile().getOptions(),
213+
descriptor.getMessageType().getName()), '.'), beanContainer);
211214
default:
212215
throw new MappingException("Unable to find " + descriptor.getJavaType());
213216
}
214217
}
215218

216-
private static String[] getFullyQualifiedClassName(DescriptorProtos.FileOptions options, String name) {
217-
if (options.getJavaMultipleFiles()) {
218-
return new String[] {options.getJavaPackage(), name};
219+
private static String[] getFullyQualifiedClassName(Descriptors.Descriptor container, final FileOptions fileOpts, String name) {
220+
221+
if (fileOpts.getJavaMultipleFiles()) {
222+
LinkedList<String> fqnSegments = new LinkedList<>();
223+
fqnSegments.push(name);
224+
while (container != null) {
225+
fqnSegments.push(container.getName());
226+
container = container.getContainingType();
227+
}
228+
fqnSegments.push(fileOpts.getJavaPackage());
229+
return fqnSegments.toArray(new String[] {});
219230
}
220231

221-
return new String[] {options.getJavaPackage(), options.getJavaOuterClassname(), name};
232+
return new String[] {fileOpts.getJavaPackage(), fileOpts.getJavaOuterClassname(), name};
222233
}
223234

224235
@SuppressWarnings("unchecked")
225236
private static Class<? extends Enum> getEnumClassByEnumDescriptor(Descriptors.EnumDescriptor descriptor, BeanContainer beanContainer) {
226-
String name = StringUtils.join(getFullyQualifiedClassName(descriptor.getFile().getOptions(), descriptor.getName()), '.');
237+
String name = StringUtils.join(getFullyQualifiedClassName(descriptor.getContainingType(), descriptor.getFile().getOptions(), descriptor.getName()), '.');
227238
return (Class<? extends Enum>)MappingUtils.loadClass(name, beanContainer);
228239
}
229240

dozer-integrations/dozer-proto3/src/test/java/com/github/dozermapper/protobuf/functional_tests/ProtoBeansMultipleFilesMappingTest.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,12 @@
1717

1818
import com.github.dozermapper.core.DozerBeanMapperBuilder;
1919
import com.github.dozermapper.core.Mapper;
20+
import com.github.dozermapper.protobuf.vo.proto.TestContainerObject;
2021
import com.github.dozermapper.protobuf.vo.proto.NestedObject;
2122
import com.github.dozermapper.protobuf.vo.proto.TestObject;
23+
import com.github.dozermapper.protobuf.vo.proto.TestContainerObject.TestContainedEnum;
24+
import com.github.dozermapper.protobuf.vo.protomultiple.ContainerObject;
25+
import com.github.dozermapper.protobuf.vo.protomultiple.ContainerObject.ContainedEnum;
2226
import com.github.dozermapper.protobuf.vo.protomultiple.SimpleProtoTestObject;
2327

2428
import org.junit.BeforeClass;
@@ -68,4 +72,37 @@ public void canSimpleFromProto() {
6872
assertNotNull(result.getNested().getOne());
6973
assertEquals(simpleProtoTestObject.getNested().getOne(), result.getNested().getOne());
7074
}
75+
76+
@Test
77+
public void canNestedObjectToProto() {
78+
TestContainerObject containerObject = new TestContainerObject();
79+
containerObject.setEnum1(TestContainedEnum.VALUE2);
80+
containerObject.setObj1(new TestContainerObject.TestContainedObject());
81+
containerObject.getObj1().setC1("ABC");
82+
83+
ContainerObject result = mapper.map(containerObject, ContainerObject.class);
84+
assertNotNull(result);
85+
assertNotNull(result.getEnum1());
86+
assertNotNull(result.getObj1());
87+
assertNotNull(result.getObj1().getC1());
88+
assertEquals(containerObject.getObj1().getC1(), result.getObj1().getC1());
89+
assertEquals(containerObject.getEnum1().name(), result.getEnum1().name());
90+
}
91+
92+
@Test
93+
public void canNestedObjectFromProto() {
94+
ContainerObject.Builder containerBuiler = ContainerObject.newBuilder();
95+
containerBuiler.setEnum1(ContainedEnum.VALUE2);
96+
containerBuiler.setObj1(ContainerObject.ContainedObject.newBuilder().setC1("ABC").build());
97+
ContainerObject container = containerBuiler.build();
98+
TestContainerObject result = mapper.map(container, TestContainerObject.class);
99+
assertNotNull(result);
100+
assertNotNull(result.getEnum1());
101+
assertNotNull(result.getObj1());
102+
assertNotNull(result.getObj1().getC1());
103+
assertEquals(container.getObj1().getC1(), result.getObj1().getC1());
104+
assertEquals(container.getEnum1().name(), result.getEnum1().name());
105+
106+
107+
}
71108
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
* Copyright 2005-2018 Dozer Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.github.dozermapper.protobuf.vo.proto;
17+
18+
public class TestContainerObject {
19+
public enum TestContainedEnum {
20+
VALUE1, VALUE2;
21+
}
22+
23+
public static class TestContainedObject{
24+
private String c1;
25+
26+
public TestContainedObject() {
27+
28+
}
29+
30+
public String getC1() {
31+
return c1;
32+
}
33+
34+
public void setC1(String c1) {
35+
this.c1 = c1;
36+
}
37+
}
38+
39+
private TestContainedObject obj1;
40+
private TestContainedEnum enum1;
41+
42+
public TestContainerObject() {
43+
}
44+
45+
public TestContainedEnum getEnum1() {
46+
return enum1;
47+
}
48+
49+
public TestContainedObject getObj1() {
50+
return obj1;
51+
}
52+
53+
public void setEnum1(TestContainedEnum enum1) {
54+
this.enum1 = enum1;
55+
}
56+
57+
public void setObj1(TestContainedObject obj1) {
58+
this.obj1 = obj1;
59+
}
60+
}

dozer-integrations/dozer-proto3/src/test/proto/ProtoTestObjectsMultipleFiles.proto

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,18 @@ message TestObject {
2525
message SimpleProtoTestObject {
2626
TestObject nested = 1;
2727
}
28+
29+
message ContainerObject {
30+
31+
enum ContainedEnum {
32+
VALUE1 = 0;
33+
VALUE2 = 1;
34+
}
35+
36+
message ContainedObject {
37+
string c1 = 1;
38+
}
39+
40+
ContainedObject obj1 = 1;
41+
ContainedEnum enum1 = 2;
42+
}

dozer-integrations/dozer-proto3/src/test/resources/mappings/protoBeansMapping.xml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,4 +87,26 @@
8787
</field>
8888
</mapping>
8989

90+
<mapping wildcard="false">
91+
<class-a>com.github.dozermapper.protobuf.vo.proto.TestContainerObject.TestContainedObject</class-a>
92+
<class-b>com.github.dozermapper.protobuf.vo.protomultiple.ContainerObject.ContainedObject</class-b>
93+
<field>
94+
<a>c1</a>
95+
<b>c1</b>
96+
</field>
97+
</mapping>
98+
99+
<mapping wildcard="false">
100+
<class-a>com.github.dozermapper.protobuf.vo.proto.TestContainerObject</class-a>
101+
<class-b>com.github.dozermapper.protobuf.vo.protomultiple.ContainerObject</class-b>
102+
<field>
103+
<a>obj1</a>
104+
<b>obj1</b>
105+
</field>
106+
<field>
107+
<a>enum1</a>
108+
<b>enum1</b>
109+
</field>
110+
</mapping>
111+
90112
</mappings>

0 commit comments

Comments
 (0)