Skip to content

Commit

Permalink
HSEARCH-5024 Adjust the CodeSource to be able to handle the new URL s…
Browse files Browse the repository at this point in the history
…tructure of the nested jars from Spring

(cherry picked from commit c1ebd6b)
  • Loading branch information
marko-bekhta authored and yrodiere committed Dec 4, 2023
1 parent a36b78b commit 81b2314
Show file tree
Hide file tree
Showing 6 changed files with 297 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
diff --git a/test/java/org/hibernate/search/integrationtest/spring/repackaged/application/RepackagedApplicationIT.java b/integrationtest/mapper/orm-spring-uberjar/application/src/test/java/org/hibernate/search/integrationtest/spring/repackaged/application/RepackagedApplicationIT.java
--- a/test/java/org/hibernate/search/integrationtest/spring/repackaged/application/RepackagedApplicationIT.java
+++ b/test/java/org/hibernate/search/integrationtest/spring/repackaged/application/RepackagedApplicationIT.java
@@ -15,6 +15,7 @@
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.jar.JarEntry;
+import java.util.jar.JarFile;

import org.hibernate.search.mapper.pojo.mapping.definition.annotation.ProjectionConstructor;
import org.hibernate.search.util.common.SearchException;
@@ -32,7 +33,8 @@

import acme.org.hibernate.search.integrationtest.spring.repackaged.model.MyEntity;
import acme.org.hibernate.search.integrationtest.spring.repackaged.model.MyProjection;
-import org.springframework.boot.loader.jar.JarFile;
+import org.springframework.boot.loader.net.protocol.Handlers;
+import org.springframework.boot.loader.net.protocol.jar.JarUrl;

/**
* This test is NOT a @SpringBootTest:
@@ -83,9 +85,9 @@
@Test
public void canReadJar() throws Exception {
try ( JarFile outerJar = new JarFile( repackedJarPath.toFile() ) ) {
- for ( JarEntry jarEntry : outerJar ) {
+ for ( JarEntry jarEntry : outerJar.stream().toList() ) {
if ( jarEntry.getName().contains( "hibernate-search-integrationtest-spring-repackaged-model" ) ) {
- URL innerJarURL = outerJar.getNestedJarFile( jarEntry ).getUrl();
+ URL innerJarURL = innerJarUrl( jarEntry );

try ( URLClassLoader isolatedClassLoader = new URLClassLoader( new URL[] { innerJarURL }, null ) ) {
Class<?> classInIsolatedClassLoader = isolatedClassLoader.loadClass( MyEntity.class.getName() );
@@ -106,8 +106,7 @@
classInfo = index.getClassByName( DotName.createSimple( MyProjection.class.getName() ) );
assertThat( classInfo ).isNotNull();
assertThat(
- classInfo.annotations()
- .get( DotName.createSimple( ProjectionConstructor.class.getName() ) ) )
+ classInfo.annotations( DotName.createSimple( ProjectionConstructor.class.getName() ) ) )
.isNotNull();
name = classInfo.field( "name" );
assertThat( name ).isNotNull();
@@ -130,4 +132,9 @@
}
}
}
+
+ URL innerJarUrl(JarEntry jarEntry) {
+ Handlers.register();
+ return JarUrl.create( repackedJarPath.toFile(), jarEntry );
+ }
}
135 changes: 135 additions & 0 deletions orm6/integrationtest/mapper/orm-spring-uberjar/application/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.hibernate.search</groupId>
<artifactId>hibernate-search-integrationtest-spring-repackaged-orm6</artifactId>
<version>6.2.3-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<artifactId>hibernate-search-integrationtest-spring-repackaged-application-orm6</artifactId>

<name>Hibernate Search ITs - Spring Repackaged JAR Application - ORM6</name>

<properties>
<transform.original.pathFromRoot>integrationtest/mapper/orm-spring-uberjar/application</transform.original.pathFromRoot>
</properties>

<dependencies>
<dependency>
<groupId>org.hibernate.search</groupId>
<artifactId>hibernate-search-integrationtest-spring-repackaged-model-orm6</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate.search</groupId>
<artifactId>hibernate-search-mapper-orm-orm6</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate.search</groupId>
<artifactId>hibernate-search-backend-lucene</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<exclusions>
<!-- Using JBoss Logging -->
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>

<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<!-- Using JBoss Logging -->
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-loader</artifactId>
<version>${version.org.springframework.boot}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hibernate.search</groupId>
<artifactId>hibernate-search-util-internal-integrationtest-mapper-orm-orm6</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
</dependencies>


<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${version.org.springframework.boot}</version>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
<configuration>
<outputDirectory>${project.build.directory}</outputDirectory>
<finalName>app-repackaged</finalName>
<mainClass>
org.hibernate.search.integrationtest.spring.repackaged.application.Application
</mainClass>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<configuration>
<skip>${failsafe.spring.skip}</skip>
<classesDirectory>${project.build.outputDirectory}</classesDirectory>
<environmentVariables>
<!--
The test settings add a different suffix to this value for each test execution.
We can't add this suffix (${random.uuid}) here due to IDEA limitations:
IDEA just ignores this environment variable if it finds a reference to an unknown property
such as "${random.uuid}".
-->
<LUCENE_ROOT_PATH>${project.build.directory}/test-indexes/</LUCENE_ROOT_PATH>
</environmentVariables>
<systemPropertyVariables>
<test.launcher-command>${java-version.test.launcher}</test.launcher-command>
<test.repackaged-jar-path>${project.build.directory}/app-repackaged.jar</test.repackaged-jar-path>
</systemPropertyVariables>
</configuration>
<executions>
<execution>
<id>it</id>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

34 changes: 34 additions & 0 deletions orm6/integrationtest/mapper/orm-spring-uberjar/model/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.hibernate.search</groupId>
<artifactId>hibernate-search-integrationtest-spring-repackaged-orm6</artifactId>
<version>6.2.3-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<artifactId>hibernate-search-integrationtest-spring-repackaged-model-orm6</artifactId>

<name>Hibernate Search ITs - Spring Repackaged JAR Model - ORM6</name>

<properties>
<transform.original.pathFromRoot>integrationtest/mapper/orm-spring-uberjar/model</transform.original.pathFromRoot>
</properties>

<dependencies>
<dependency>
<groupId>org.hibernate.search</groupId>
<artifactId>hibernate-search-mapper-orm-orm6</artifactId>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>

55 changes: 55 additions & 0 deletions orm6/integrationtest/mapper/orm-spring-uberjar/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.hibernate.search</groupId>
<artifactId>hibernate-search-integrationtest-orm6</artifactId>
<version>6.2.3-SNAPSHOT</version>
<relativePath>../..</relativePath>
</parent>
<artifactId>hibernate-search-integrationtest-spring-repackaged-orm6</artifactId>
<packaging>pom</packaging>

<name>Hibernate Search ITs - Spring Repackaged JAR</name>
<description>Testing if Hibernate Search will start correctly inside a Spring's repackaged jar</description>

<modules>
<module>model</module>
<module>application</module>
</modules>

<properties>
<!--
Remove Hibernate system properties from parent settings:
They are supposed to be handled by the spring.datasource subsystem
and not by the Hibernate internal pool!
See also the failsafe configuration.
-->
<failsafe.jvm.args.hibernate-orm></failsafe.jvm.args.hibernate-orm>
<version.org.springframework.boot>3.2.0</version.org.springframework.boot>
</properties>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${version.org.springframework.boot}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- The Spring BOM uses a version of bytebuddy that's too old for Mockito to work correctly -->
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy</artifactId>
<version>${version.net.bytebuddy}</version>
</dependency>
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy-agent</artifactId>
<version>${version.net.bytebuddy}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>

12 changes: 12 additions & 0 deletions orm6/integrationtest/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,18 @@
<module>java/modules/orm-coordination-outbox-polling-elasticsearch</module>
</modules>
</profile>
<profile>
<id>springITs</id>
<activation>
<property>
<name>java-version.test.release</name>
<value>!8</value>
</property>
</activation>
<modules>
<module>mapper/orm-spring-uberjar</module>
</modules>
</profile>
</profiles>
</project>

Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,13 @@ class CodeSource implements Closeable {
private static final Log log = LoggerFactory.make( Log.class, MethodHandles.lookup() );

private static final String JAR_URI_PATH_SEPARATOR = "!/";
// Starting with Spring Boot 3.2 the nested jars in a repackaged app will be using an url structure as:
// * "jar:nested:/.../app-repackaged.jar/!BOOT-INF/classes/!/"
// * jar:nested:/.../app-repackaged.jar/!BOOT-INF/lib/some-packaged-lib.jar!/
// that means that we will get the `nested:...` as a path when extracting the nested path.
// Spring should be able to handle loading the files for such jars using their own custom filesystem and handlers
// hence as soon as we discover such path we let it be handled by them.
private static final String NESTED_SPEC_PREFIX = "nested:";
private static final BiFunction<Path, URI, FileSystem> NESTED_JAR_FILESYSTEM_CREATOR;

static {
Expand Down Expand Up @@ -185,7 +192,7 @@ private void tryInitJarFileSystem(URI jarUri) throws IOException {

private Path extractedJarNestedPath(URI jarUri) {
String spec = jarUri.getSchemeSpecificPart();
if ( spec == null ) {
if ( spec == null || spec.startsWith( NESTED_SPEC_PREFIX ) ) {
return null;
}
int pathSeparatorIndex = spec.indexOf( JAR_URI_PATH_SEPARATOR );
Expand Down

0 comments on commit 81b2314

Please sign in to comment.