我想从用户那里获取几个Maven依赖项列表,解析并加载它们作为包含的应用程序。以下是步骤:
给出一些上下文:我想在UIMA的上下文中使用上述内容,以便能够运行依赖于具有不同版本的不同库集的不同(自然语言处理)管道。我的目标是创建一个注释服务器,其中一个定义(Maven)依赖项和可以以RESTful方式调用的管道。管道(及其相应的依赖项)应该在包含的类路径环境中运行(以避免类路径冲突)。
OSGi是否可行?基于类路径(:=已解析的jar列表),我可以构建一个OSGi包并进行部署吗?全部以编程方式?我无法控制maven依赖项(它们是UIMA组件,它就是它),因此无法在那里添加OSGi元数据。
答案 0 :(得分:2)
maven-assembly-plugin与maven配置文件相结合可以为您解决这个问题吗?
您可以基于每个配置文件以不同方式过滤依赖项。您可以使用特定于配置文件的程序集描述符文档并生成要置于战争中的自定义清单。您正在描述J2EE Web应用程序(war)程序集 - 它们将在servlet容器内的防火墙类加载器中运行,因此您可以基于相同的源生成一堆它们(只需更改Web应用程序上下文和WEB的内容 - 基于每个配置文件的INF / lib。
例如,将它们放入同一个Tomcat服务器中,您就可以开始了。这是你的意思吗?
HTH,
尼克
答案 1 :(得分:1)
您当然可以创建一个包含jar列表的bundle,将所有这些放在bundle自己的类路径中,并将该bundle部署到OSGi容器中。您可能需要创建一个BundleActivator(它是该bundle的入口点,就像传统Java的main方法一样)。
然后您说您有多个此类捆绑包,并且我是否正确理解您要将每个捆绑包部署在单独的容器中?如果是这样,您可以使用某种REST库为每个捆绑包提供REST端点,也可以使用OSGi远程服务发布可由其他容器发现的服务。
我不确定这是不是你的意思,所以我也不确定OSGi是否是正确的选择。根据您的描述,您既不使用服务(使用OSGi的一个非常重要的原因,因为它将应用程序的各个部分相互分离),也不打算为组件创建不同的包(使用OSGi的另一个重要原因)。您几乎将当前被大肆宣传的建筑风格描述为“微服务”。你能详细说明一下吗?
答案 2 :(得分:1)
这听起来很像你可以使用Apache Stanbol。它是一个专注于内容语义增强的框架,但可用于涉及内容的任何基于Web的工作流程。您可以定义管道以处理和/或存储数据。使用Apache Tika和OpenNLP有NLP的组件。据我所知,你也可以整合UIMA。它使用RESTful服务,基于OSGI。
如果Stanbol不适合您的用例并且您需要推出自己的应用程序,我认为OSGI仍然是可行的方法。
根据您的使用情况,您可以将软件包部署到容器,或者只是将OSGI框架嵌入到一个小型启动器应用程序中,该应用程序可以加载您创建的软件包。
许多Maven工件已经包含OSGI元数据。大多数情况下,您可以使用maven-dependency-plugin将它们复制到捆绑目录,并将它们直接加载为OSGI捆绑包。
非OSGI依赖项可以嵌入到需要它们的bundle中。还应该可以设置一些maven插件来修改清单,根据maven工件ID和版本添加一些元数据,并将依赖关系重新打包为捆绑(虽然从Maven开始,但它不会一直工作pom版本和软件包的版本并不总是一样的。
可以使用maven-bundle-plugin捆绑用户代码和任何所需的依赖项。它可以为您生成清单。
对于REST接口,我通常会推荐JAX-RS(Jersey或Apache CXF DOSGI),但我还没有使用这些框架的编程方法。
答案 3 :(得分:1)
根据您的使用情况,我建议您查看Java ServiceLoader API。 ServiceLoader API允许您定义接口,并从不同的自包含JAR加载该接口的实现。您可以将不同的库构建到自己的jar中,通过接口公开所需的方法,并从Java程序中独立加载它们。 ServiceLoader甚至会列出可供您使用的不同实现。
从文档中: 假设我们有一个服务类型com.example.CodecSet,它用于表示某些协议的编码器/解码器对的集合。在这种情况下,它是一个抽象类,有两个抽象方法:
public abstract Encoder getEncoder(String encodingName);
public abstract Decoder getDecoder(String encodingName);
每个方法返回一个适当的对象,如果提供者不支持给定的编码,则返回null。典型的提供程序支持多种编码。 如果com.example.impl.StandardCodecs是CodecSet服务的实现,那么它的jar文件还包含一个名为
的文件META-INF/services/com.example.CodecSet
此文件包含单行:
com.example.impl.StandardCodecs # Standard codecs
CodecSet类在初始化时创建并保存单个服务实例:
private static ServiceLoader<CodecSet> codecSetLoader
= ServiceLoader.load(CodecSet.class);
要找到给定编码名称的编码器,它会定义一个静态工厂方法,该方法遍历已知和可用的提供程序,仅在找到合适的编码器或用完提供程序时返回。
public static Encoder getEncoder(String encodingName) {
for (CodecSet cp : codecSetLoader) {
Encoder enc = cp.getEncoder(encodingName);
if (enc != null)
return enc;
}
return null;
}
getDecoder方法的定义类似。