GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Support for JSpecify nullness annotations · Issue #1243 · mapstruct/mapstruct

Support for JSpecify nullness annotations #1243

New issue
Copy link
New issue
Copy link
Closed
#4033
Closed
Support for JSpecify nullness annotations#1243
#4033
Copy link
Labels
enhancementfor:team-discussion
Milestone
1.7.0.Beta2

Description

@PCasafont
PCasafont
opened on Jul 9, 2017
Issue body actions

Currently, when we create an update mapping such as:
User updateUserFromDto(@MappingTarget User user, UserDto userDto);

In order to have null checks, we must configure the Mapper annotation (in the class level) to have nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS.

But this generates null checks everywhere, including the creator mappers.
It would be awesome if there was a property in @mapping like "nullCheck=true/false", so that we can fully control that.

Reacted by cs-StephanieDM, Paraita Wohler, Amr, Björn Seebeck, Mark, James O'Cull, Valentin, Joan Pujol, Guido, scalatel and 62 more
Pinned by filiphr
Pinned comment options
@filiphrfiliphron Apr 19, 2026

For everyone's information. The decision has ben made that MapStruct will only support JSpecify annotations.

If you are using libraries that do not use JSpecify then I would advise you to raise issues / PRs for those libraries to add support for JSpecify as well. If you can't raise PRs, then please share them with the community, maybe someone else will have the time and do contributions. Let's help and move the community forward.

View full comment

Activity

Next
  1. filiphr
    added
    enhancement
    on Jul 16, 2017
  2. filiphr commented on Jul 16, 2017

    @filiphr
    filiphr
    on Jul 16, 2017
    Member
    More actions

    Doing it on the @Mapping is one way to do it.

    I think that it could be better if we can check for NotNull or Nullable annotations on the getters. This is what IntelliJ does for the code inspections. I also think that Kotlin uses those annotations as for interoperability with Java. Spring has also done it for their entire code base, see SPR-15540. I am not sure about other frameworks.

    WDYT?

    Reacted by David Belmez Vicente and Kernevez
  3. PCasafont commented on Jul 16, 2017

    @PCasafont
    PCasafont
    on Jul 16, 2017 via email
    Author
    More actions
    A check for nullable/notnull annotations would be awesome!
  4. filiphr
    added this to the Future planning milestone on Jul 16, 2017
  5. filiphr
    added
    for:team-discussion
    on Jul 16, 2017
  6. filiphr
    changed the title [-]A way to explicitly tell which source fields to null check[/-] [+]Support for NonNull / Nullable annotations[/+] on Jun 1, 2018
  7. brunomarquete commented on May 5, 2020

    @brunomarquete
    brunomarquete
    on May 5, 2020
    More actions

    Are there plans to start this feature? I am working with non-null objects in Kotlin and I would like to see this feature implemented in MapStruct.

    Reacted by vladyslavv-ua and Kernevez
  8. altarasyuk commented on Jun 17, 2020

    @altarasyuk
    altarasyuk
    on Jun 17, 2020
    More actions

    It would be good feature

  9. mdelmoral commented on Oct 26, 2020

    @mdelmoral
    mdelmoral
    on Oct 26, 2020
    More actions

    In my current company we use the library in small and not very critical services since we are very strict with the validation of nullity. This feature would be fundamental to adopt the library at a global level 👍🏻

  10. darioseidl commented on Mar 16, 2021

    @darioseidl
    darioseidl
    on Mar 16, 2021
    More actions

    For Java, JSR 303 support would be nice. Similarly for Kotlin, it would be great if the implementation could create null-checks depending on the nullability of the Kotlin types in the mapper interface.

    For example, in the PersonConverter all types are non-nullable, but in the generated PersonConverterImpl, null would be passed through instead of throwing an exception.

    Reacted by Martin-BG
    Reacted by David Belmez Vicente
  11. andye2004 commented on Mar 25, 2021

    @andye2004
    andye2004
    on Mar 25, 2021
    More actions

    This would be an incredibly valuable feature and something that would encourage greater adoption of MapStruct. Are there any plans to start this work given the ticket has been open for close to four years now?

    Reacted by Martin-BG, Aravind Parappil, Minghao Wang (王铭浩), Daniel Olivera, William Holmes, NICK-T-D, pat-karakun, Anand, Arley Henostroza, Tina1992 and 5 more
  12. anandbhaskaran commented on Apr 25, 2022

    @anandbhaskaran
    anandbhaskaran
    on Apr 25, 2022
    More actions

    This would be incredibly nice to have a feature!

    Reacted by socar-jian, Ramazan Girgin, Raul Ferreira, Augusto, Michael Cramer, Patrick Lampe Dittmer, Toni Mangas, Anton and Kyran Rana
  13. agentgt commented on Jan 5, 2023

    @agentgt
    agentgt
    on Jan 5, 2023
    More actions

    The fact that MapStruct does not handle @Nullable annotations particularly TYPE_USE aka JSR 308 annotations (e.g. JSpecify and Checker) is a major reason I have the generator run and just copy the code back into the abstract class (or interface) as a concrete inner class (I rely entirely on constructor based mapping so new fields easily become compile errors and thus the maintenance of adding a new field is not that painful).

    This is because if you run null analysis like Eclipse (which arguably is kind of broken but mostly follows JSpecify) or Checkerframework you will get warnings all over the place for conditional checking for null and or worse doesn't force the user to deal with mapping something potentially nullable to nonnull.

    What fundamentally needs to happen IMO is that MapStruct should treat e.g. java.lang. @Nullable String (n.b. how TYPE_USE annotations declared different) as a different type than java.lang.String because it actually is in terms of static analysis.

    This becomes really complicated when dealing with code generation particularly generics and arrays.

    MapStruct pulls all fields that need to be mapped out as variables:

    public record SomeType(List<@Nullable String> list, @Nullable String string){}

    The mapping code then should produce code like:

    List<@Nullable String> list = someType.list();
    @Nullable String string = someType.string();
    //... snip the setting or calling of constructor

    Instead of:

    List<String> list = someType.list();
    String string = someType.string();
    //... snip the setting or calling of constructor

    That is the annotations should follow the type regardless of whether MapStruct tries to do things based on the semantics of @Nullable. Unfortunately this is inherently difficult with the current JDK annotation processor framework as it will often either strip the annotations or worse incorrectly print them (a JDK bug that is kind of fixed in 19).

    Furthermore mapping methods will need to be annotation aware. For example say I do have @Nullable String -> String.

    String convertNullable(@Nullable String s) {
    }

    MapStruct should know to call that method to convert the nullable string type to a nonnull (or in this case stripped annotation) string type. After all it is a different type.

  14. filiphr commented on Mar 17, 2023

    @filiphr
    filiphr
    on Mar 17, 2023
    Member
    More actions

    Thanks for your examples @agentgt.

    MapStruct should know to call that method to convert the nullable string type to a nonnull (or in this case stripped annotation) string type. After all it is a different type.

    I am not sure that MapStruct should treat methods with types annotated differently as different types. I would rather have MapStruct properly detect NonNull / Nullable annotations and invoke the methods appropriately.

    Regarding the code that we should generate, I don't see a reason why not to generate code with passing down the annotations on the return type itself. However, that topic is different than this issue and I would suggest creating a separate issue where we can discuss MapStruct generating such code (irregardless of the bugs in the compilers)

  15. agentgt commented on Mar 17, 2023

    @agentgt
    agentgt
    on Mar 17, 2023
    More actions

    I am not sure that MapStruct should treat methods with types annotated differently as different types. I would rather have MapStruct properly detect NonNull / Nullable annotations and invoke the methods appropriately

    But they mostly are. It is like the difference between String? and String in kotlin. The reason I brought up the whole TYPE_USE annotation following support isn't as much about generating the code but rather force the user to convert through some mechanism (as a configurable option).

    If the annotations follow then the static null analysis will fail (compile failure) and MapStruct does not have to do any magic on trying to figure out how to map nullables to nonnull. I would call that nullable support "Level 1" which would require MapStruct (as a configurable option) to stop doing if (x == null) checks. MapStruct just assumes everything is NonNull! I would be happy with just that option today (I haven't played with updated MapStruct but I assume its still not an option of disable null checking). e.g NullValueCheckStrategy.NEVER is missing.

    "Level 2" support would be to have MapStruct fail (instead of the compiler or null analysis) when it sees: @Nullable T -> T (as well as the inverse) and force manual conversion. Whether that is for any TYPE_USE annotation or not is an exercise in configuration.

    That is because basically it is like mapping Optional<T> -> T. MapStruct should fail here. I don't know what it currently does but if it makes T null that is bad.

    "Level 3" would be knowing that @Nullable is a wider type. That is T -> @Nullable T is a an obvious NOOP mapping but @Nullable T -> T requires conversion.

    that topic is different than this issue and I would suggest creating a separate issue where we can discuss MapStruct generating such code (irregardless of the bugs in the compilers)

    I can but the two are highly related. @Nullable T should be treated like Optional<T>. If you don't think of it as types its going to get much harder as things like Valhalla and JSpecify. At some point you will have to check if the type supports if (t == null) or not just like it is a primitive.

    Reacted by Floris Kraak, socar-jian, Suman Maity and Floyd Kretschmar
  16. 22 remaining items

  17. filiphr
    added 2 commits that reference this issue on Apr 6, 2026

    Add support for JSpecify nullness annotations (mapstruct#1243)

    5177f9f

    Add support for JSpecify nullness annotations (mapstruct#1243)

    4557780
  18. filiphr
    modified the milestones: 1.7.x, 1.7.0.Beta2 on Apr 12, 2026
  19. filiphr commented on Apr 12, 2026

    @filiphr
    filiphr
    on Apr 12, 2026
    Member
    More actions

    I finally found the time to work on this. I've created PR #4033 that is tackling this. I've decided to only support JSpecify, since it seems that the ecosystem has converged on that. Would really appreciate if all the interested parties have a look at the PR and provide any feedback that they have.


    To answer some of the comments that people have posted.

    Thanks @nealeu for sharing those links. It looks interesting from Java point of view. I feel confident that once that lands in Java we could adjust the approach I've taken in the PR to support that. We might need a bit more refactoring for treating the types differently, but it'll work. The example you provided will lead to a compiler error, unless you explicitly provide a defaultValue or defaultExpression for mapping the lastName.

    e.g.

    @Mapper
    @NullMarked
    interface Mapper {
      Target fromSource(Source source);
    }

    leads to compiler error

    Can't map potentially nullable source property "lastName" to @NonNull constructor parameter "lastName". Consider adding a defaultValue or defaultExpression.

    Whereas

    @Mapper
    @NullMarked
    interface Mapper {
    
      @Mapping(target = "lastName", defaultValue = "unknown")
      Target fromSource(Source source);
    }

    would compile.

    Reacted by Mathis Guillet, Karkoon, Alex and Toni Birka
  20. filiphr
    added 2 commits that reference this issue on Apr 13, 2026

    Fix JSpecify nullness edge cases and expand test coverage

    3f781e5

    Harden JSpecify nullness support and surface decisions

    3a7880d
  21. filiphr
    closed this as completedin #4033on Apr 19, 2026
  22. filiphr
    added a commit that references this issue on Apr 19, 2026

    #1243 Add support for JSpecify nullness annotations (#4033)

    9554065
  23. filiphr
    changed the title [-]Support for NonNull / Nullable annotations[/-] [+]Support for JSpecify nullness annotations[/+] on Apr 19, 2026
  24. filiphr commented on Apr 19, 2026

    @filiphr
    filiphr
    on Apr 19, 2026 · Pinned by filiphr
    Member
    More actions

    For everyone's information. The decision has ben made that MapStruct will only support JSpecify annotations.

    If you are using libraries that do not use JSpecify then I would advise you to raise issues / PRs for those libraries to add support for JSpecify as well. If you can't raise PRs, then please share them with the community, maybe someone else will have the time and do contributions. Let's help and move the community forward.

    Reacted by Jannik Schäfer, Kernevez, Neale Upstone, Karkoon, Alex, Toni Birka and Ruslan Suleymanov
  25. filiphr
    pinned a comment on Apr 19, 2026
  26. filiphr
    added a commit that references this issue on Apr 26, 2026

    Include upstream commits missing from fork in changelog

    fc8ae72
  27. filiphr
    added a commit that references this issue on May 15, 2026

    mapstruct#4056 Extend JSpecify support for container mapping and @non…

    19c830d
  28. filiphr
    added a commit that references this issue on Jun 5, 2026

    #4056 Extend JSpecify support for container mapping and @nonnull retu…

    35334e5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementfor:team-discussion

    Type

    No type

    Projects

    No projects

      Milestone

      • 1.7.0.Beta2

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      You are visitor 01402503 — GeezerVison does not store the pages you look up.
      Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.