ITKeyword,专注技术干货聚合推荐

注册 | 登录

解决java - How to access common resource files from multiple projects

itPublisher 分享于

2020腾讯云双十一活动,全年最低!!!(领取3500元代金券),
地址https://cloud.tencent.com/act/cps/redirect?redirect=1073

【阿里云】双十一活动,全年抄底价,限时3天!(老用户也有),
入口地址https://www.aliyun.com/1111/home

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?

java maven resources dbunit
|
  this question
edited Feb 7 '14 at 13:16 Drunix 2,733 7 17 40 asked Jan 23 '14 at 17:40 FazoM 1,644 3 19 38

 | 

8 Answers
8

解决方法 +50

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.


|
  this answer
edited Feb 17 '14 at 8:37 answered Feb 7 '14 at 12:15 Drunix 2,733 7 17 40      How come? I use relative path.. it is relative to project root. (?) –  FazoM Feb 8 '14 at 10:42      getResourceAsStream tries to load the Resource from classpath. It is absolute because it starts searching at the root of each classpath entry. A relative path would not Start with a slash and would be searched relative to the current package. So your path is not absolute regarding you filesystem, but absolute in Java sense. –  Drunix Feb 8 '14 at 11:37      Ok. fair enough –  FazoM Feb 8 '14 at 12:18

 | 

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"


|
  this answer
answered Jan 23 '14 at 17:43 evanchooly 4,082 6 19      That's right, my mistake in copy-pasting. Question is still valid though. –  FazoM Jan 23 '14 at 17:45 1   That absolute path is "absolute" against a classpath root. so if you put it in a jar or even an exploded directory, it will be found via the classpath not any particular location on disk. So as long as your classpath is correct, that path will be portable across every installation. –  evanchooly Jan 23 '14 at 17:47      But classpaths are different for different projects, right? (I have rich maven modules hierarchy) –  FazoM Jan 23 '14 at 17:49      The classpath will vary in that, e.g., paths to jars on a windows file system will differ from those on linux. But to your app, it's just a classpath and so your code is shielded from such variations and can be Written Once and Run Anywhere. –  evanchooly Jan 23 '14 at 18:46      But those projects (modules) are being build separately. I'm most interested in maven's integration-test phase for each of them as this Util class is used for testing (with dbunit). –  FazoM Jan 23 '14 at 19:11  |  show more comments

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;

|
  this answer
answered Jan 31 '14 at 17:11 Hannes 1,201 10 18      I will try this (after the weekend probably) and will give you an update, but I think it may work. Thanks! –  FazoM Jan 31 '14 at 17:21      @Hannes - your application shouldn't know about the build tool used to build it or the folder structure expected by that tool. What if you want to use a resource from another project that is not part of your code base or doesn't use maven's layout? Java's classpath does this for you without having to know project layouts. –  ike_love Feb 6 '14 at 17:00      @ike_love Pardon? I can't follow you thoughts. –  Hannes Feb 6 '14 at 19:06      @Hannes - your solution uses absolute paths and only works for resources that are part of a JAR exploded during the build. The standard Java way of using a resource from a JAR is to use classpath, not to explode the jar and refer to that resource directly. –  ike_love Feb 6 '14 at 20:12      @ike_love Are you sure you comment the right post? This is a rather typical setup for building a maven plugin. At this phase sources-generate we are not realy talking about jar but folders with sources and resources. And of course the annotated paths are just defaults which can be overriten being the configuration you set. –  Hannes Feb 6 '14 at 21:37  |  show more comments

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.


|
  this answer
answered Feb 5 '14 at 20:14 ike_love 3,453 15 30

 | 

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


|
  this answer
edited Feb 6 '14 at 14:32 answered Feb 6 '14 at 14:27 Ashkan 175 1 11

 | 

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
  common resources across multiple web applications.


|
  this answer
edited Feb 4 '14 at 5:21 answered Feb 3 '14 at 5:11 Kaustabh 81 4

 | 

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.


|
  this answer
edited Feb 5 '14 at 15:59 answered Feb 5 '14 at 15:23 thomas.mc.work 4,527 2 11 28

 | 

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.


|
  this answer
answered Feb 7 '14 at 6:28 Yogesh_D 3,383 1 14 34

 | 


相关阅读排行


相关内容推荐

最新文章

×

×

请激活账号

为了能正常使用评论、编辑功能及以后陆续为用户提供的其他产品,请激活账号。

您的注册邮箱: 修改

重新发送激活邮件 进入我的邮箱

如果您没有收到激活邮件,请注意检查垃圾箱。