我开发了一个 Java 实用程序库(类似于 Apache Commons),我在各种项目中使用它。
除了胖客户端之外,我还将它用于移动客户端(具有 J9 Foundation 配置文件的 PDA)。
随着时间的推移,作为单个项目开始的库扩展到多个包中。结果,我最终得到了很多功能,但并不是所有项目都真正需要这些功能。
由于这个库也在一些移动/PDA 项目中使用,我需要一种方法来收集使用的类并生成实际的专用 jar。
目前,在使用该库的项目中,我有 Ant jar 任务(从实用程序项目)生成专用 jar 文件(例如:my-util-1.0-pda.jar、my-util-1.0-rcp.jar)使用包含/排除 jar 任务功能。由于移动项目生成的 jar 文件的大小限制,这主要是需要的。
现在迁移到 Maven 我只是想知道是否有任何最佳实践可以实现类似的目标。我考虑以下场景:
[1] - 除了主 jar 工件(my-lib-1.0.jar)之外,也在 my-lib 内部生成strong> 使用 Maven Jar 插件或 Maven 程序集插件过滤/包含,使用分类器(例如:my-lib-1.0-pda.jar)来项目单独/专门的工件。我对这种方法不太满意,因为它会因图书馆消费者的需求(过滤器)而污染图书馆。
[2] - 为所有专门的客户端/项目创建额外的 Maven 项目,这将“包装”“my-lib”并生成过滤后的 jar 工件(例如:my-lib-包装器-pda-1.0 ...等)。因此,这些包装器项目将包括过滤(以生成过滤后的工件),并且仅依赖于“my-lib”项目,而客户端项目将依赖于 my-lib-wrapper-xxx-1.0< /strong> 而不是 my-lib-1.0。这种方法可能看起来有问题,因为即使这样也会让“my-lib”项目完好无损(没有额外的分类器和工件),基本上会使项目数量加倍,因为对于每个客户端项目,我都会有一个库,只是为了收集所需的“my-util”库中的类(“my-pda-app”项目将需要“my-lib-wrapper-for-my-pda-app”项目/依赖项)。
[3] - 在使用该库的每个客户端项目(例如:my-pda-app)中添加一些专门的 Maven 插件来修剪(生成最终工件时/ package) 不需要的类(例如:maven-assemble-plugin、maven-jar-plugin、proguard-maven-plugin)。
以“Maven方式”解决此类问题的最佳实践是什么?
I developed a Java utility library (similarly to Apache Commons) that I use in various projects.
In addition to fat clients, I also use it for mobile clients (PDA with J9 Foundation profile).
In time the library that started as a single project spread over multiple packages. As a result I end up with a lot of functionality, which is not really needed in all the projects.
Since this library is also used inside some mobile/PDA projects I need a way to collect just the used classes and generate the actual specialized jars.
Currently in the projects that are using this library, I have Ant jar tasks that generate (from the utility project) the specialized jar files (ex: my-util-1.0-pda.jar, my-util-1.0-rcp.jar) using include/exclude jar task features. This is mostly needed due to the size constraints on the generated jar file, for the mobile projects.
Migrating now to Maven I just wonder if there are any best practices to arrive to something similar. I consider the following scenarios:
[1] - additionally to the main jar artifact (my-lib-1.0.jar) also generating inside my-lib project the separate/specialized artifacts using classifiers (ex: my-lib-1.0-pda.jar) using Maven Jar Plugin or Maven Assembly Plugin filtering/includes. I'm not very comfortable with this approach since it pollutes the library with library consumers demands (filters).
[2] - Create additional Maven projects for all the specialized clients/projects, that will "wrap" the "my-lib" and generate the filtered jar artifacts (ex: my-lib-wrapper-pda-1.0 ...etc). As a result, these wrapper projects will include the filtering (to generate the filtered artifact) and will depend just on the "my-lib" project and the client projects will depend on my-lib-wrapper-xxx-1.0 instead of my-lib-1.0. This approach may look problematic since even that will let "my-lib" project intact (with no additional classifiers and artifacts), basically will double the number of projects since for every client project I'll have one lib, just to collect the needed classes from the "my-util" library ("my-pda-app" project will need a "my-lib-wrapper-for-my-pda-app" project/dependency).
[3] - In every client project that uses the library (ex: my-pda-app) add some specialized Maven plugins to trim out (when generating the final artifact/package) the classes that are not required (ex: maven-assembly-plugin, maven-jar-plugin, proguard-maven-plugin).
What is the best practice for solving this kind of problems in the "Maven way"?
发布评论
评论(1)
出于模块化考虑,Maven 的一般规则是“每个 POM 一个主要工件”,并且不应违反这一约定(一般情况下)的原因在 如何从一个项目 (. ..以及为什么你不应该) 博客文章。然而,也存在合理的例外(例如,生成 EJB JAR 的 EJB 项目和仅具有接口的客户端 EJB JAR)。话虽如此:
提到的 博客文章(另请检查当您无法使用约定时使用 Maven)解释了如何使用单独的配置文件或 JAR 插件来实现选项 1。如果您决定实现此解决方案,请记住这应该是一个例外,并且它可能会使依赖项管理变得更加棘手(并且,正如您所提到的,用“客户端过滤逻辑”污染项目)。为了以防万一,我会在这里使用几个 JAR 插件执行。
选项 2 与选项 1 IMO 没有太大区别(除了它分开的东西):基本上,拥有 N 个其他包装/过滤项目与拥有 N 个过滤规则非常相似在一个项目中。如果过滤有意义,我更喜欢选项 1。
我根本不喜欢选项 3,因为我认为“删除”不需要的东西不应该是图书馆客户的责任。首先,客户端项目不一定具备所需的知识(要修剪什么),其次,这可能会与其他插件造成很大的混乱。
但是如果胖客户端不使用整个my-lib(就像服务器端代码需要整个EJB JAR),那么过滤不是处理您的情况的正确“行家方式”。正确的方法是选项 4:将所有常见内容放入项目中(生成my-lib-core-1.0.jar),并将特定部分放入特定项目中(将生成my-lib-pda-1.0.jar 等)。然后,客户将依赖于核心工件和专用工件。
The Maven general rule is "one primary artifact per POM" for the sake of modularity and the reasons one shouldn't break this convention (in general) are very well explained in the How to Create Two JARs from One Project (...and why you shouldn’t) blog post. There are however justified exceptions (for example an EJB project producing an EJB JAR and a client EJB JAR with only interfaces). Having said that:
The mentioned blog post (also check Using Maven When You Can't Use the Conventions) explains how you could implement Option 1 using separate profiles or the JAR plugin. If you decide to implement this solution, keep in mind that this should be an exception and that it might make dependency management trickier (and, as you mentioned, pollute the project with "client filtering logic"). Just in case, I would use several JAR plugin executions here.
Option 2 isn't very different from Option 1 IMO (except that it separate things): basically, having N other wrapping/filtering projects is very similar with having N filtering rules in one project. And if filtering makes sense, I prefer Option 1.
I don't like Option 3 at all because I think it shouldn't be the responsibility of a client of a library to "trim out" unwanted things. First, a client project doesn't necessarily have the required knowledge (what to trim) and, second, this might create a big mess with other plugins.
BUT if the fat clients are not using the whole my-lib (like server-side code would require the whole EJB JAR), then filtering isn't the right "maven way" to handle your situation. The right way would be Option 4: put everything common in a project (producing my-lib-core-1.0.jar) and specific parts in specific projects (that will produce my-lib-pda-1.0.jar etc). Clients would then depend on the core artifact and specialized ones.