Spring Load-Time Weaving

Are you struggling with performance issues in your Spring, Jakarta EE, or Java EE application?

What if there were a tool that could automatically detect what caused performance issues in your JPA and Hibernate data access layer?

Wouldn’t it be awesome to have such a tool to watch your application and prevent performance issues during development, long before they affect production systems?

Well, Hypersistence Optimizer is that tool! And it works with Spring Boot, Spring Framework, Jakarta EE, Java EE, Quarkus, Micronaut, or Play Framework.

So, rather than fixing performance issues in your production system on a Saturday night, you are better off using Hypersistence Optimizer to help you prevent those issues so that you can spend your time on the things that you love!

Introduction

In this article, we are going to see how Spring load-time weaving works so that you can apply the Hibernate bytecode enhancement mechanism at runtime.

Traditionally, the bytecode enhancement mechanism is applied when the project is built using a Maven or Gradle plugin. For more details about the build-time approach, check out this article.

Domain Model

Let’s consider we have the following Attachment entity that has a content property that is mapped as follows:

@Lob
@Column(columnDefinition="BLOB")
@Basic(fetch = FetchType.LAZY)
private byte[] content;

The content property is using the FetchType.LAZY fetching strategy, but loading entity attributes lazily cannot be done on POJO entities, so we need the Hibernate bytecode enhancement mechanism to achieve this goal.

Hibernate Bytecode Enhancement Mechanism

The Hibernate bytecode enhancement mechanism allows us to change the bytecode of a JPA entity so that we can intercept the getter and the setter method calls in order to:

  • load attributes lazily
  • record entity modifications

Most often, the bytecode enhancement mechanism is configured via a Maven or Gradle plugin, which enhances the entity classes when the project is built, as explained in this article.

However, this is not the only approach we can use since we can also instrument the JPA entity classes at runtime when the project is bootstrapped.

Spring Data JPA Load-Time Weaving

To enable the runtime bytecode enhancement mechanism when bootstrapping a Spring application, you have to add the @EnableLoadTimeWeaving annotation to your Spring configuration:

@EnableLoadTimeWeaving
public class BytecodeEnhancementConfiguration {
    ...
}

Now, we need to provide the Spring Instrumentation library to the JVM via the javaagent argument. If you’re using Windows, you could do it like this:

-javaagent:%M2_REPOSITORY%\org\springframework\spring-instrument\%SPRING_VERSION%\spring-instrument-%SPRING_VERSION%.jar

That’s it!

Testing Time

When loading an Attachment entity and accessing the content property:

Attachment book = attachmentRepository.findById(1L).orElseThrow(null);

LOGGER.debug("Fetched book: {}", book.getName());

assertArrayEquals(readBytes(bookFilePath), book.getContent());

We can see that the content column is not fetched by the first SQL query, being fetched on demand in a secondary SQL query:

SELECT 
    a.id,
    a.media_type,
    a.name 
FROM 
    attachment a 
WHERE 
    a.id = 1

-- Fetched book: High-Performance Java Persistence

SELECT 
    a.content 
FROM 
    attachment a 
WHERE 
    a.id = 1

Awesome, right?

If you enjoyed this article, I bet you are going to love my Book and Video Courses as well.

Conclusion

Using the Spring load-time weaving mechanism can be very useful if we want to enhance the JPA entity classes without having access to the project build.

The @EnableLoadTimeWeaving annotation tells Spring to register a LoadTimeWeaver bean that will be provided to the JPA EntityManagerFactory to enhance the JPA entities that get loaded, giving us the opportunity to enable the bytecode enhancement lazy loading or dirty tracking mechanisms.

Transactions and Concurrency Control eBook

2 Comments on “Spring Load-Time Weaving

  1. It doesn’t work for me, it says I need special class loader

    org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘loadTimeWeaver’ defined in class path resource [org/springframework/context/annotation/LoadTimeWeavingConfiguration.class]:

    • I tried to run the example as well but got this problem:

      Caused by: java.lang.LinkageError: loader 'app' attempted duplicate class definition for jakarta.persistence.TemporalType. (jakarta.persistence.TemporalType is in unnamed module of loader 'app')
      

      That is caused by HHH-18108 which was fixed in 6.5.3, but I don’t see it on Maven Central. I will have to check it again after that release to see if the test is working. If it’s not, it’s because of some Spring or Hibernate bug.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.