すべてのDTOを生成するのにimmutables frameworkを使用しています。今度は、mapstructを使ってこれらのオブジェクトを互いにマップしたいと思います。しかし生成されたDTOは不変であり、ビルダーパターンに対応するセッターとコンストラクターを持たない。それらは、静的なbuilder()
メソッドによってアクセスされる対応するBuilderを介してのみ満たされます。mapstructでビルダー(immutables注釈プロセッサを使用)でオブジェクトを不変オブジェクトにマッピングする
代わりに、mapstructがビルダーのセッターを認識するようにDTO1をDTO2.Builderにマップしようとしましたが、これらは戻り値の型がvoidではなく、流暢な連結のためにBuilder自体を返します。
ここに例のコードを示します。私たちは工場を必要とするビルダーを見つけるためmapstructについては
@Mapper(uses = ObjectFactory.class)
public interface SourceTargetMapper {
SourceTargetMapper MAPPER = Mappers.getMapper(SourceTargetMapper.class);
ImmutableMammalEntity.Builder toTarget(MammalDto source);
}
:
は、我々は2つのインタフェース
@Value.Immutable
public interface MammalDto {
public Integer getNumberOfLegs();
public Long getNumberOfStomachs();
}
と
@Value.Immutable
public interface MammalEntity {
public Long getNumberOfLegs();
public Long getNumberOfStomachs();
}
はその後、我々はmapstructためのマッパー・インターフェースを持っています:
public class ObjectFactory {
public ImmutableMammalDto.Builder createMammalDto() {
return ImmutableMammalDto.builder();
}
public ImmutableMammalEntity.Builder createMammalEntity() {
return ImmutableMammalEntity.builder();
}
}
コンパイラプラグインは、両方の注釈プロセッサを使用するように指示されたコードを生成するために:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<annotationProcessorPaths>
<path>
<groupId>org.immutables</groupId>
<artifactId>value</artifactId>
<version>2.2.8</version>
</path>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.2.0.Beta3</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
注:これはのみ mapstructのバージョンで動作します> 1.2.xでは古いバージョンでは、クリーンビルド(mvn clean compile
)で、immutablesが作成したばかりのソースが見つからないという問題があります。 2番目のビルド(クリーンではない)では、注釈プロセッサが実行される前にクラスパス上にあったので、immutablesの実装が見つかります。このバグは修正されました。
これは魅力的です。最初に、インターファクトの不変の実装が生成され、mapstructがそれを使用してビルダーを生成します。
@Test
public void test() {
MammalDto s = ImmutableMammalDto.builder().numberOfLegs(4).numberOfStomachs(3l).build();
MammalEntity t = SourceTargetMapper.MAPPER.toTarget(s).build();
assertThat(t.getNumberOfLegs()).isEqualTo(4);
assertThat(t.getNumberOfStomachs()).isEqualTo(3);
}
ザ・失敗アサート:
しかし、テストは何のプロパティが設定されていないことを示しています。 mapstructによって生成されたマッパーを見てみると、明らかにセッターが見つかりませんでした。
@Generated(
value = "org.mapstruct.ap.MappingProcessor",
//...
)
public class SourceTargetMapperImpl implements SourceTargetMapper {
private final ObjectFactory objectFactory = new ObjectFactory();
@Override
public Builder toTarget(MammalDto source) {
if (source == null) {
return null;
}
Builder builder = objectFactory.createMammalEntity();
return builder;
}
}
空のビルダーが返されます。私はそれが流暢なAPIを作成するために自分自身を返すための理由が発生したビルダーのセッターの実装だと思う:
public final Builder numberOfLegs(Long numberOfLegs) {
this.numberOfLegs = Objects.requireNonNull(numberOfLegs, "numberOfLegs");
return this;
}
はmapstructは、これらのセッターを見つけてみましょうする方法はありますか?ビルダーにこのような不変のオブジェクトを扱う良い方法は?
編集:私がコメントに述べたように、私はIssue #782に走った。バージョン1.2.0ではまだビルダーはサポートされていません。しかし、このトピックについてはいくつかの議論があるので、同じ問題がある場合は、その問題に従うのが面白いかもしれません。
私は既知の問題に遭遇したアンドレアスGudianで述べたように、独自のアノテーション
と、使用中、これらの設定を定義することができます。機能要求#782「ビルダーによる不変オブジェクトのマッピング」は、バージョン1.1.0.Beta2として公開されています。サンプルはmapstructの統合テストモジュールにあります。私は次の反復で特定のニーズにこの慣用句を適応させます。具体的な実施の提案は大歓迎です。 Java-Model-APIはちょっと難しいと思われます... –