Question

In one of my projects I have resources stored in /src/test/resources (typical maven directory structure). Those resources are being used by an utility class stored in the project.

The utility class itself is being used from other projects (other projects depend on this one). I would access the resource like that:

final InputStream inputStreamDobs = 
    ClassLoader.class.getResourceAsStream("/dbunit/clear_db.xml");

but since I use it from different projects the path is not correct - it is relative to current project that is being built/tested, not the one where utility class and resources are.

Any thought how to approach this?

I need to avoid absolute paths - would like to have a way of defining relative path to the utility class.

I also don't want to replicate resources over multiple projects. Cheers.

EDIT: To give a context I have a definition of tables in XML file that needs to be cleared after Integration Tests (clear whole DB schema). Integration Tests sits in multiple project, but the clear script and resource file is the same for all of them and sits in common parent project.

EDIT2:

Bonus question: I would like to access common DTD file (let's call it tables.dtd) that need to be accessed from XML files from multiple other projects. (it will sit in common parent project).

Currently I have it duplicated over multiple project, and I refer to it from XML using directive:

<!DOCTYPE dataset SYSTEM "src/test/resources/dbunit/dobs.dtd">

How to point it to a file in different project?

Was it helpful?

Solution

You wrote

... but since I use it from different projects the path is not correct - it is relative to current project that is being built/tested, not the one where utility class and resources are ...

Relative paths are not the problem here. You use an absolute path in your example, but even if you would use a relative one, this would refer to the package or directory structure. getResourceAsStream would pick them up as long as the classpath is correct. The real problem is that you are referring to test resources in another project. But test resources and classes are not contained in the project artifact, so they are not accessible from modules that include this as a dependency. If you need these resources for tests in several projects, I would suggest that you create a new project (let's say "projectxyz-testresources") with these resouces contained in src/main/resources and add this as a dependency with scope "test" where relevant.

EDITED TO ADD:

If you don't want to use a separate project for test resources, you can create a test-jar containing test classes and resources using goal jar:test-jar and include this as a test dependency. You may want to configure the jar plugin in your pom to execute this goal on regular builds.

OTHER TIPS

Your runtime classpath shouldn't reference src/test/resources. Maven will copy everything over to target so you should be able to get it with "/dbunit/clear_db.xml"

Have you tried using "classpath:" prefix? You shouldn't have to specify full paths to resources if they are available on the classpath. For example:

<mvc:resources location="classpath:/META-INF/web-resources/" mapping="/resources/**" />

/META-INF/web-resources/ comes from Spring MVC's JAR which is one of the project's dependencies. The project doesn't need to know how to get to that resource "directly" instead it uses the classpath.

I think you can use 2 below plugins for this purpose. if your project is web project, you can create 2 web projects, one of them contains config files and another project is your main project, now on you can overlay projects with maven-war-plugin

There are many types for overlay, you can visit this page for more information maven-war-plugin overlay

for jar files you can merge them to single one with maven-assembly-plugin

maven-assembly-plugin

We had a similar instance in which, we had some configuration files that were used across multiple modules in big multi module maven project. So what we did was split the conf files into a separate module, that just jars up the config files. And then whatever module needed those files could declare the dependency to the config files modules and just use the jar files with the config files and unzip them to use them. You could do something similar for the test resources. Create a module with just the resources and then put them into the relevant path.

In this case, I would suggest to program a maven plugin for this task, so that this so variable path may be configured via properties. You will also benefit from the Project object.

/**
 * Location of the file.
 */
@Parameter(defaultValue = "${basedir}/src/main/java", property = "sourceFolder", required = true)
private File sourceFolder;

@Parameter(defaultValue = "${basedir}/src/test/java", property = "testFolder", required = true)
private File testFolder;

@Parameter(defaultValue = "${project}", property = "project", readonly = true, required = true)
private MavenProject project;

Can you try using Maven Overlays? We had faced similar situation in the past, and very much resolved using overlays. Usually, overlays are used to share common resources across multiple web applications.

Maybe one of these approaches:

Either: You outsource the xml files AND the java classes (like the utility class) that need access to them into a seperate library which you can then include into your several other projects (conveniently as maven dependencies).

Or: You put these xml files into a seperate VCS-tree or repository and you include them in your project tree (e.g. as an "external" in SVN). So you can update this reference seperately in your projects, but you only have to maintain one source file.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top