Skip to content

Commit

Permalink
Add remove final agent to SpringBootAspectJ IT
Browse files Browse the repository at this point in the history
This helps to test
  - multi-agent embedding and execution,
  - the 'agentArgs' plugin configuration parameter.
  • Loading branch information
kriegaex committed Feb 26, 2024
1 parent 66f47ee commit 13f8a94
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 10 deletions.
13 changes: 13 additions & 0 deletions src/it/SpringBootAspectJ/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
<properties>
<java.version>8</java.version>
<aspectj.version>1.9.21</aspectj.version>
<remove-final.version>1</remove-final.version>
</properties>

<build>
Expand Down Expand Up @@ -44,6 +45,12 @@
<artifactId>aspectjweaver</artifactId>
<agentClass>org.aspectj.weaver.loadtime.Agent</agentClass>
</agent>
<agent>
<groupId>dev.aspectj</groupId>
<artifactId>remove-final-agent</artifactId>
<agentClass>dev.aspectj.agent.RemoveFinalAgent</agentClass>
<agentArgs>dev.aspectj.FirstComponent,dev.aspectj.SecondComponent</agentArgs>
</agent>
</javaAgents>
<removeEmbeddedAgents>true</removeEmbeddedAgents>
</configuration>
Expand Down Expand Up @@ -84,6 +91,12 @@
<artifactId>aspectjweaver</artifactId>
<version>${aspectj.version}</version>
</dependency>
<!-- Agent removing final modifiers from classes and methods -->
<dependency>
<groupId>dev.aspectj</groupId>
<artifactId>remove-final-agent</artifactId>
<version>${remove-final.version}</version>
</dependency>
<!-- Using these instead of spring-boot-starter makes the repackaged JAR smaller -->
<dependency>
<groupId>org.springframework.boot</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,23 @@

import org.springframework.stereotype.Component;

import static java.lang.reflect.Modifier.isFinal;

@Component
public class FirstComponent {
// Make class final to on purpose -> expect remove final agent to do its job and un-final it again
public final class FirstComponent {
@LogWriteAccess
private String field1;
private Integer field2;
private boolean field3;
@LogWriteAccess
private Double field4;

static {
if (isFinal(FirstComponent.class.getModifiers()))
System.out.println("Remove final agent seems to be inactive, class FirstComponent should be non-final");
}

public void setField1(String field1) {
this.field1 = field1;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,23 @@

import org.springframework.stereotype.Component;

import static java.lang.reflect.Modifier.isFinal;

@Component
public class SecondComponent {
// Make class final to on purpose -> expect remove final agent to do its job and un-final it again
public final class SecondComponent {
private String field1;
@LogWriteAccess
private Integer field2;
@LogWriteAccess
private boolean field3;
private Double field4;

static {
if (isFinal(SecondComponent.class.getModifiers()))
System.out.println("Remove final agent seems to be inactive, class SecondComponent should be non-final");
}

public void setField1(String field1) {
this.field1 = field1;
}
Expand Down
44 changes: 36 additions & 8 deletions src/it/SpringBootAspectJ/verify.groovy
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import java.util.zip.ZipEntry
import java.util.zip.ZipFile

/*
Expand All @@ -24,6 +25,20 @@ String mavenVersion = invokerVariablesBound ? mavenVersion : '3.9.5'
File buildLog = new File(basedir, 'build.log')
List<String> logLines = buildLog.readLines()

// --------------------------------------------------------
// Inspect Maven build output
// --------------------------------------------------------

// Embedded java agents are removed
List<String> removeEmbeddedJarLines = logLines.grep(~/.*Removing embedded java agent: .*/)
assert removeEmbeddedJarLines.size() == 2
assert removeEmbeddedJarLines.grep(~/.*BOOT-INF\/lib\/aspectjweaver-.*\.jar/).size() == 1
assert removeEmbeddedJarLines.grep(~/.*BOOT-INF\/lib\/remove-final-agent-.*\.jar/).size() == 1

// --------------------------------------------------------
// Inspect Spring Boot runtime output
// --------------------------------------------------------

// AspectJ load-time weaving (LTW) happens
List<String> weaveInfoLines = logLines.grep(~/.*weaveinfo.*/)
assert weaveInfoLines.size() == 4
Expand All @@ -32,30 +47,43 @@ assert weaveInfoLines.grep(~/.*field-set\(java.lang.Double dev.aspectj.FirstComp
assert weaveInfoLines.grep(~/.*field-set\(java.lang.Integer dev.aspectj.SecondComponent.field2\).*/).size() == 1
assert weaveInfoLines.grep(~/.*field-set\(boolean dev.aspectj.SecondComponent.field3\).*/).size() == 1

// Embedded java agent is removed
List<String> removeEmbeddedJarLines = logLines.grep(~/.*Removing embedded java agent: .*/)
assert removeEmbeddedJarLines.size() == 1
assert removeEmbeddedJarLines.grep(~/.*BOOT-INF\/lib\/aspectjweaver-.*\.jar/).size() == 1
// Remove final agent is active
assert logLines.grep(~/.*Remove final agent seems to be inactive.*/).size() == 0
assert logLines.contains('[Remove Final Agent] Removing final from class dev.aspectj.FirstComponent')
assert logLines.contains('[Remove Final Agent] Removing final from class dev.aspectj.SecondComponent')

// FieldWriteAccessLogAspect kicks in
assert logLines.contains('set(String dev.aspectj.FirstComponent.field1)')
assert logLines.contains('set(Double dev.aspectj.FirstComponent.field4)')
assert logLines.contains('set(Integer dev.aspectj.SecondComponent.field2)')
assert logLines.contains('set(boolean dev.aspectj.SecondComponent.field3)')

// --------------------------------------------------------
// Inspect executable JAR with embedded agents
// --------------------------------------------------------

// Get artifact path from Maven JAR output
List<String> buildingJarLines = logLines.grep(~/.*Building jar: .*/)
assert buildingJarLines.size() == 1
def artifactPath = buildingJarLines[0].split('Building jar: ')[1]
def artifactJarEntries = new ZipFile(artifactPath).entries().toList()

// Confirm that AspectJ weaver classes have been embedded into the executable Spring Boot JAR
int aspectjWeaverClassesFound
int aspectjWeaverJarsFound
def aspectjWeaverClasses = new ZipFile(artifactPath).entries()
def aspectjWeaverClasses = artifactJarEntries
.findAll { it.name.startsWith 'org/aspectj/weaver/' }
assert aspectjWeaverClasses.size() > 300

// Confirm that the embedded AspectJ weaver JAR has been removed from the executable Spring Boot JAR
def aspectjWeaverJars = new ZipFile(artifactPath).entries()
def aspectjWeaverJars = artifactJarEntries
.findAll { it.name ==~ /.*aspectjweaver.*\.jar/ }
assert aspectjWeaverJars.size() == 0

// Confirm that remove final agent classes have been embedded into the executable Spring Boot JAR
def removeFinalAgentClasses = artifactJarEntries
.findAll { it.name.startsWith 'dev/aspectj/agent/RemoveFinal' }
assert removeFinalAgentClasses.size() > 2

// Confirm that the embedded remove final agent JAR has been removed from the executable Spring Boot JAR
def removeFinalAgentJars = artifactJarEntries
.findAll { it.name ==~ /.*remove-final-agent.*\.jar/ }
assert removeFinalAgentJars.size() == 0

0 comments on commit 13f8a94

Please sign in to comment.