Possible false positive with SuperBuilder and java:S3252

I have a possible false positive Sonar Warning:

Use static access with “AbstractEntity” for “builder”.“static” base class members should not be accessed via derived types java:S3252

For example It is triggered by AdminExportRequest.builder() call.Both this class and its parent abstract class are using SuperBuilder from lombok.

Lombok Version is 1.18.42 and managed by Spring Boot 3.5.11I have Sonar Version: Community Build v26.3.0.120487

Here is the class definitions:

@NoArgsConstructor
@Getter@Setter
@ToString
@SuperBuilder
@EntityListeners(MyEntityListener.class)
@MappedSuperclass
@Cacheable(cacheNames = {“cache”})
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class AbstractEntity {…}

@Getter
@Setter
@Table(name = “admin_export_requests”)
@RequiredArgsConstructor
@SuperBuilder
@Entity
@EntityListeners({MyEntityListener.class})
public class AdminExportRequest extends AbstractEntity {…}

AbstractEntity is the base Class of all Entities and it has more than 50 sub-classes.It have only 12 warnings in this type related with builder.

Here code snippets for 2 example calls that has triggered the warning.

returnValue = request
.orElseGet(() → AdminExportRequest.builder()
.exportRequestStatus(ExportRequestStatus.NOT_REQUESTED)
.target(outerTarget)
.build());

protected AdminDetailsDtoV2 createDetailsDto(OtherEntity p) {
return AdminDetailsDtoV2.builder()
.id(p.getId())
.createdDate(p.getCreatedDate())
.lastModifiedDate(p.getLastModifiedDate())
.labels(loadLabels(p))
.build();
}


In the same project I have a different hierarchies but they not trigger this warning:

Non Entity parent and sub-class:

Getter
NoArgsConstructor
Setter
SuperBuilder
public abstract class FunctionContext {
}

SuperBuilder
Getter
public class DeleteAttachment extends FunctionContext {
}

This code part does not trigger any warning:

deleteAttachment.execute(DeleteAttachmentContext.builder().attachmentId(aid).build());

If this is not a false positive, how can I fix this?

AbstractEntity does not define all fields, it is enhanced by the sub-classes and I need to call concrete sub-class builder to build a valid instance.

Hi Can,

Thanks for reaching out and providing those details.

I’ve attempted to reproduce this issue locally using Lombok’s @SuperBuilder, but in my tests, the rule behaves correctly.

I did not find any tickets specifically linking @SuperBuilder and S3252 in our database. The closest related issue is SONARJAVA-4208, but it involves different annotations.

Because the provided snippets have some omissions, it’s difficult to pinpoint the root cause. To help us investigate further, could you provide a small and complete reproducer?

Best,
Tomasz

Hello Tomasz,

This is really interesting because I do get the warning after maven build on the Sonar Website but I have also InteliJ Plugin but it does not show the same warning, however InteliJ Plugin shows other warnings.

Here is the error from the Web Page:

I tried to analyze it on PoiMedia, which is a smaller entity.

@Getter
@Setter
@ToString
@RequiredArgsConstructor
@SuperBuilder
@Entity
@EntityListeners({AuditingEntityListener.class, EntityEventPublisher.class})
public class PoiMedia extends AbstractEntity {

@NotEmpty
@Size(min = 1, max = 100)
private String title;

@Size(min = 0, max = 100)
private String description;

private URL location;

@ElementCollection
@FullTextField
List<String> tags;
}

AbstractEntity:

@NoArgsConstructor
@Getter
@Setter
@ToString
@SuperBuilder
@EntityListeners(AuditingEntityListener.class)
@MappedSuperclass
@Cacheable(cacheNames = {"mycache"})
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class AbstractEntity {

    @Transient
    private final List<? extends ApplicationEvent> events = new ArrayList<>();

    @Id
    @GeneratedValue(generator = "UUID")
    @UuidGenerator
    private String id;

    @CreatedDate
    @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
    @GenericField(sortable = Sortable.YES)
    private Instant createdDate;

    @LastModifiedDate
    @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
    @GenericField(sortable = Sortable.YES)
    private Instant lastModifiedDate;

    @Version
    private Long version;

    @DomainEvents
    public Collection<? extends ApplicationEvent> domainEvents() {
        return events;
    }

    @AfterDomainEventPublication
    void callbackMethod() {
        events.clear();
    }

     public Instant getLastModifiedDate() {
        return (lastModifiedDate == null) ? null : lastModifiedDate.truncatedTo(ChronoUnit.MILLIS);
    }

    public Instant getCreatedDate() {
        return (createdDate == null) ? null : createdDate.truncatedTo(ChronoUnit.MILLIS);
    }
}

I tried to copy both PoiMedia and AbstractEntity into a different package to generate a simple example that I can reproduce, I just renamed the classes with “My” prefix.
Code from below does not trigger this warning, however original PoiMedia builder call is causing this warning.

@Component
@Slf4j
public class MyUploadPoiMedia {

    public MyUploadPoiMediaResult executeFunction(MyUploadPoiMediaContext context) {

        MyPoiMedia poiMedia = MyPoiMedia.builder()
                .title(null)
                .description(null)
                .location(null)
                .tags(null)
                .build();

        return MyUploadPoiMediaResult.builder()
                .result(poiMedia)
                .review(null)
                .build();
    }
}

Here is the complete original function where builder call is executed and warning is triggered:

    @Override
    public UploadPoiMediaResult executeFunction(UploadPoiMediaContext context) {


        String name = context.getFilename();
        byte[] content = context.getContent();
        URL url = upload.internal(UploadImageContext.builder()
                        .owner(context.getReview().getAuthor())
                        .content(content)
                        .filename(name)
                        .objectId(UUID.randomUUID().toString())
                        .description("")
                        .contentType(context.getContentType())
                        .build())
                .getResult();

        List<String> tags = context.getTags();
        String description = context.getDescription();
        String title = context.getTitle();
        if (title == null || "".equals(title)) {
            title = name;
        }

        PoiMedia poiMedia = PoiMedia.builder()
                .title(title)
                .description(description)
                .location(url)
                .tags(tags)
                .build();
        poiMedia = poiMediaRepository.save(poiMedia);

        Review review = context.getReview();
        List<PoiMedia> images = review.getImages();
        if (images == null) {
            images = new ArrayList<>();
            review.setImages(images);
        }
        images.add(poiMedia);
        review = reviewRepository.save(review);

        return UploadPoiMediaResult.builder()
                .result(poiMedia)
                .review(review)
                .build();
    }

Currently I get only 7 instances of this warning, but actually much more calls done for the builders.

Best Regards,
Can