Java unmapped target properties

mapstruct-ignore-unmapped-properties

In Java applications, we may wish to copy values from one type of Java bean to another. To avoid long, error-prone code, we can use a bean mapper such as MapStruct.

While mapping identical fields with identical field names is very straightforward, we often encounter mismatched beans. In this tutorial, we’ll look at how MapStruct handles partial mapping.

2. Mapping

MapStruct is a Java annotation processor. Therefore, all we need to do is to define the mapper interface and to declare mapping methods. MapStruct will generate an implementation of this interface during compilation.

For simplicity, let’s start with two classes with the same field names:

Next, let’s create a mapper interface:

@Mapper public interface CarMapper

Finally, let’s test our mapper:

@Test public void givenCarEntitytoCar_whenMaps_thenCorrect()

3. Unmapped Properties

As MapStruct operates at compile time, it can be faster than a dynamic mapping framework. It can also generate error reports if mappings are incomplete — that is, if not all target properties are mapped:

Warning:(X,X) java: Unmapped target property: "propertyName".

While this is is a helpful warning in the case of an accident, we may prefer to handle things differently if the fields are missing on purpose.

Читайте также:  Read php book online

Let’s explore this with an example of mapping two simple objects:

public class DocumentDTO < private int id; private String title; private String text; private Listcomments; private String author; >

We have unique fields in both classes that are not supposed to be filled during mapping. They are:

If we define a mapper interface, it will result in warning messages during the build:

@Mapper public interface DocumentMapper

As we do not want to map these fields, we can exclude them from mapping in a few ways.

4. Ignoring Specific Fields

To skip several properties in a particular mapping method, we can use the ignore property in the @Mapping annotation:

@Mapper public interface DocumentMapperMappingIgnore

Here, we’ve provided the field name as the target and set ignore to true to show that it’s not required for mapping.

However, this technique is not convenient for some cases. We may find it difficult to use, for example, when using big models with a large number of fields.

5. Unmapped Target Policy

To make things clearer and the code more readable, we can specify the unmapped target policy.

To do this, we use the MapStruct unmappedTargetPolicy to provide our desired behavior when there is no source field for the mapping:

  • ERROR: any unmapped target property will fail the build – this can help us avoid accidentally unmapped fields
  • WARN: (default) warning messages during the build
  • IGNORE: no output or errors

In order to ignore unmapped properties and get no output warnings, we should assign the IGNORE value to the unmappedTargetPolicy. There are several ways to do it depending on the purpose.

5.1. Set a Policy on Each Mapper

We can set the unmappedTargetPolicy to the @Mapper annotation. As a result, all its methods will ignore unmapped properties:

@Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE) public interface DocumentMapperUnmappedPolicy < // mapper methods >

5.2. Use a Shared MapperConfig

We can ignore unmapped properties in several mappers by setting the unmappedTargetPolicy via @MapperConfig to share a setting across several mappers.

First we create an annotated interface:

@MapperConfig(unmappedTargetPolicy = ReportingPolicy.IGNORE) public interface IgnoreUnmappedMapperConfig

Then we apply that shared configuration to a mapper:

@Mapper(config = IgnoreUnmappedMapperConfig.class) public interface DocumentMapperWithConfig < // mapper methods >

We should note that this is a simple example showing the minimal usage of @MapperConfig, which might not seem much better than setting the policy on each mapper. The shared config becomes very useful when there are multiple settings to standardize across several mappers.

5.3. Configuration Options

Finally, we can configure the MapStruct code generator’s annotation processor options. When using Maven, we can pass processor options using the compilerArgs parameter of the processor plug-in:

   org.apache.maven.plugins maven-compiler-plugin $ $ $  org.mapstruct mapstruct-processor $   -Amapstruct.unmappedTargetPolicy=IGNORE     

In this example, we’re ignoring the unmapped properties in the whole project.

6. The Order of Precedence

We’ve looked at several ways that can help us to handle partial mappings and completely ignore unmapped properties. We’ve also seen how to apply them independently on a mapper, but we can also combine them.

Let’s suppose we have a large codebase of beans and mappers with the default MapStruct configuration. We don’t want to allow partial mappings except in a few cases. We might easily add more fields to a bean or its mapped counterpart and get a partial mapping without even noticing it.

So, it’s probably a good idea to add a global setting through Maven configuration to make the build fail in case of partial mappings.

Now, in order to allow unmapped properties in some of our mappers and override the global behavior, we can combine the techniques, keeping in mind the order of precedence (from highest to lowest):

  • Ignoring specific fields at the mapper method-level
  • The policy on the mapper
  • The shared MapperConfig
  • The global configuration

7. Conclusion

In this tutorial, we looked at how to configure MapStruct to ignore unmapped properties.

First, we looked at what unmapped properties mean for mapping. Then we saw how partial mappings could be allowed without errors, in a few different ways.

Finally, we learned how to combine these techniques, keeping in mind their order of precedence.

As always, the code from this tutorial is available over on GitHub.

Источник

Java: Unmapped target properties

I have a problem with Mapper.I am using a mapstruct-processor to build Maven project. All time I get a warning:
Warning:(15, 16) java: Unmapped target properties: “from, to”.
Warning:(13, 13) java: Unmapped target properties: “clientFrom, clientTo”.
What did I suppose to do with that? Class Client works well and creates a Client.

 @Entity public class Message < @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String message; @ManyToOne(cascade = ) @JoinColumn(name = "client_from") private Client clientFrom; @ManyToOne @JoinColumn(name = "client_to") private Client clientTo; public Message()<> public Long getId() < return id; >public void setId(Long id) < this.id = id; >public String getMessage() < return message; >public void setMessage(String message) < this.message = message; >public Client getClientFrom() < return clientFrom; >public void setClientFrom(Client clientFrom) < this.clientFrom = clientFrom; >public Client getClientTo() < return clientTo; >public void setClientTo(Client clientTo) < this.clientTo = clientTo; >> public class MessageDTO < private Long id; private String message; private ClientDTO from; private ClientDTO to; public MessageDTO()<>public Long getId() < return id; >public void setId(Long id) < this.id = id; >public String getMessage() < return message; >public void setMessage(String message) < this.message = message; >public ClientDTO getFrom() < return from; >public void setFrom(ClientDTO from) < this.from = from; >public ClientDTO getTo() < return to; >public void setTo(ClientDTO to) < this.to = to; >> @Mapper(componentModel = "spring", uses = ) public interface MessageMapper < Message toMessage(MessageDTO messageDTO); MessageDTO toMessageDTO(Message message); ListtoMessageList(List list); List toMessageDTOList(List list); > 

Solution – 1

The error Unmapped target properties: «» is usually represented on the appropriate methods and in your case it means that MapStruct could not find from and to for the mapping of MessageDTO toMessageDTO(Message message) and clientFrom and clientTo for the mapping of Message toMessage(MessageDTO messageDTO) .

To solve this you will have to explicitly define the mappings between the different properties.

Your mapper will look like (I am assuming mapstruct-jdk8 usage):

@Mapper(componentModel = "spring", uses = ) public interface MessageMapper < @Mapping(target = "clientFrom", source = "from") @Mapping(target = "clientTo", source = "to") Message toMessage(MessageDTO messageDTO); @InheritInverseConfiguration //MapStruct will automatically reverse the defined mappings from toMessage MessageDTO toMessageDTO(Message message); ListtoMessageList(List list); List toMessageDTOList(List list); > 

For better understanding have a look at here. In the documentation. For more info about the @InheritInverseConfiguration have a look here.

If the names of the properties (getters / setters) were the same in Message and MessageDTO , then you wouldn’t need the @Mapping annotations

Solution – 2

In the latest versions of MapStruct you can:

  1. Define @Mapping annotation with ignore=true attribute for any field that should not be mapped OR
  2. Add special reporting policy to your mapper interface to suppress warnings on all unmapped fields at once, like this:
@Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE) 

Источник

Saved searches

Use saved searches to filter your results more quickly

You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session. You switched accounts on another tab or window. Reload to refresh your session.

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unmapped target properties #21

Unmapped target properties #21

Comments

Warning:java: Unmapped target properties: «wzdm, dl, tempid, usernameCreate, userCreate».

The text was updated successfully, but these errors were encountered:

How to disable this warning?

My clarification: this warning is a little annoying if you want to map entities to views/DTO or views/DTO to entities. In such scenario you will almost always have some unmapped properties (intentionally), because if you want to have all properties mapped between these two objects, why would you use mapstruct? You could just expose your domain object instead.

@l0co are you referring to the compilation warning?

This is not linked with the IntelliJ plugin. You have multiple options to avoid this:

Yes — the compilation warning. Thanks for your hint, I removed all our warnings now. However it would be useful to have an option to disable them by default, as now they can be disabled manually per each mapper only.

Have you read about the Configuration options in our documentation? You can disable them via a compiler option. However, I strongly advise against using the compiler option. I always advise to explicitly define what you need too map

I overlooked these options, thanks!

Heh, it looks in java 10 the compiler option causes another warning (both gradle and Idea):

Information:javac 10 was used to compile java sources Information:10.05.18 09:08 - Compilation completed successfully with 1 warning in 3s 64ms Warning:java: The following options were not recognized by any processor: '[mapstruct.unmappedTargetPolicy]' 

We haven’t really tested MapStruct with Java 10, but it should work. Are you still getting the unmapped target properties, or not?

Are you still getting the unmapped target properties, or not?

With -Amapstruct.unmappedTargetPolicy=IGNORE there’s no more errors about unmapped properties. However there’s persistent The following options were not recognized by any processor warning (don’t know if it’s related to JDK 10). Because of this I’ve sadly needed to get back to per-mapper annotation option because I’ve spent almost two hours to get rid of this, without any success (only -Xlint:none works).

FYI: We need to have absolutely no warnings in the build process. Because we heavily use JDK serialization we need to ensure that each Serializable class has serialVersionUID field and we use warnings for that with -Xlint:serial -Werror options. So either first of second class of warnings related to mapstruct is harmful for us.

If you don’t see any MapStruct warnings with -Amapstruct.unmappedTargetPolicy=IGNORE then there is a processor that consumes that option 😄 .

The problem you are seeing might be if you have a multi module project and you set that property for all modules, but you have the MapStruct compiler only for some modules. The other explanation would be that something has changed in JDK 10 and we are not marking that property as consumed, or the JDK 10 compiler has some bug,

That’s interesting. I’ve extracted separate testcase and . you’re right. This problem is somehow related to our multi module project structure. However, the warning is shown for both kinds of submodules — these using mapstruct, and these not. We will try to dig into this.

@l0co I am not sure if you resolved your problem. However, I think that it might be related to mapstruct/mapstruct#1638. You might want to look into the test compile outputting this as well.

I am going to close this issue for now as there is nothing that the plugin can do

Источник

Оцените статью