During a Spring Boot migration from 2.6.6 to 3.3.0, I had to migrate MapStruct from 1.4.2.Final to 1.5.5.Final. Now, I have a problem with a GraphQL request.
In pom.xml :
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<compilerArgs>
<arg>-parameters</arg>
</compilerArgs>
<annotationProcessorPaths>
<path>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<version>${spring-boot.version}</version>
</path>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${mapstruct.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
graphql request : http://localhost:8080/services/myservice/graphql
query GetDevice($deviceCode: String) {
getDevice(deviceCode: $deviceCode) {
id
code
name
description
deviceType {
id
code
name
description
printerTemplate {
id
code
name
description
}
}
webDevicePrinter {
id
code
name
description
width
height
}
}
}
with
{
"deviceCode": "code-01"
}
reponse before migration :
{
"data": {
"getDevice": {
"allowMultiPayment": null,
"id": "2bea1324-4d69-478c-b93d-70b746c9813f",
"code": "code-01",
"name": "code-01",
"description": null,
"deviceType": {
"id": "f687102c-f485-4da1-8e01-407b2d44465a",
"code": "POSMOB",
"name": "Pos Mobile",
"description": null,
"printerTemplate": null
},
"webDevicePrinter": {
"id": "dce48d75-3d07-4ed2-b2ff-47ac0200b82c",
"code": "printercode",
"name": "printer-01",
"description": "printer 01",
"width": 47,
"height": null
}
}
}
}
After migration
{
"data": {
"getDevice": {
"allowMultiPayment": null,
"id": "2bea1324-4d69-478c-b93d-70b746c9813f",
"code": "code-01",
"name": "code-01",
"description": null,
"deviceType": {
"id": "f687102c-f485-4da1-8e01-407b2d44465a"
},
"webDevicePrinter": {
"id": "dce48d75-3d07-4ed2-b2ff-47ac0200b82c"
}
}
}
}
in graphqls file :
type Device {
id: ID
code: String
name: String
description: String
deviceType: DeviceType
webDevicePrinter: WebDevice
}
type DeviceType {
id: ID
code: String
name: String
description: String
printerTemplate: PrinterTemplate
}
type WebDevice {
id: ID!
code: String
name: String
description: String
width: Int
height: Int
}
type PrinterTemplate {
id: ID
code: String
name: String
description: String
printMsg: String
}
extend type Query {
getDevice(deviceCode: String): Device
}
java Query :
import org.springframework.graphql.data.method.annotation.Argument;
import org.springframework.graphql.data.method.annotation.QueryMapping;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.stereotype.Controller;
@Transactional
@Controller
public class PosQuery {
@QueryMapping
public DeviceDTO getDevice(@Argument String deviceCode) {
if (deviceCode != null && !deviceCode.isBlank()) {
DeviceCriteria criteria = new DeviceCriteria();
StringFilter codeFilter = new StringFilter();
codeFilter.setEquals(deviceCode);
criteria.setCode(codeFilter);
List<DeviceDTO> resultList = deviceQueryService.findByCriteria(criteria);
if (!resultList.isEmpty()) {
return resultList.get(0);
}
}
return null;
}
}
deviceQueryService was generated by jhipster before migration :
Here, deviceRepository.findAll(specification) give a List with all fields i want, but after the application of toDto, i have only id
@Transactional(readOnly = true)
public List<DeviceDTO> findByCriteria(DeviceCriteria criteria) {
log.debug("find by criteria : {}", criteria);
final Specification<Device> specification = createSpecification(criteria);
return deviceMapper.toDto(deviceRepository.findAll(specification));
}
DeviceMapper :
@Mapper(
componentModel = "spring",
uses = {
GlobalMethodMapper.class,
DeviceTypeMapper.class,
WebDeviceMapper.class,
DeviceMapper.InnerResolver.class,
},
nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS
)
public interface DeviceMapper extends com.adeiz.cs.tech.mapper.EntityMapper<DeviceDTO, Device> {
@Mapping(target = "deviceType", source = "deviceType", qualifiedByName = "id")
@Mapping(target = "webDevicePrinter", source = "webDevicePrinter", qualifiedByName = "id")
DeviceDTO toDto(Device s);
default List<DeviceDTO> toDto(List<Device> devices) {
if (devices == null) {
return null;
}
return devices.stream().map(this::toDto).collect(Collectors.toList());
}
in DeviceType i have :
@BeanMapping(ignoreByDefault = true)
@Mapping(target = "id", source = "id")
DeviceTypeDTO toDtoId(DeviceType deviceType, @Context CycleAvoidingContext context);
@Named("id")
@BeanMapping(ignoreByDefault = true)
@Mapping(target = "id", source = "id")
default DeviceTypeDTO toDtoId(DeviceType deviceType) {
return toDtoId(deviceType, new CycleAvoidingContext(true));
}
public class CycleAvoidingContext {
private boolean fromList;
public CycleAvoidingContext() {
this(false);
}
public CycleAvoidingContext(boolean fromList) {
this.fromList = false;
this.fromList = fromList;
}
public boolean isFromList() {
return this.fromList;
}
public void setFromList(boolean fromList) {
this.fromList = fromList;
}
}
I tried to debug before and after migration, i didn’t see a diference.
I added this in application.yml :
management:
endpoints:
jackson:
isolated-object-mapper: false
but nothing