简体   繁体   English

如何仅将我的 Java 库中的异常传递给实施应用程序?

[英]How can I pass only Exceptions from my Java Library to the implementing application?

According to the Gradle Documentation you can include a dependency as "API" meaning it will be passed on to the application implementing it's class path.根据Gradle 文档,您可以将依赖项包含为“API”,这意味着它将传递给实现其 class 路径的应用程序。 Is there a way to pass only an individual class/exception instead of the entire dependency?有没有办法只传递一个单独的类/异常而不是整个依赖项?

Example例子

In Library A (written by me) I am using Open SAML Core.在库 A(由我编写)中,我使用的是 Open SAML Core。 The Class CoolClass in the library throws Exception B (from Open SAML Core).库中的 Class CoolClass 引发异常 B(来自 Open SAML 核心)。 The build.gradle file includes: build.gradle文件包括:

dependencies {
    implementation group: 'org.opensaml', name: 'opensaml-core', version: "24.0.2"

In Java Application C, I am implementing Library A. If I use CoolClass in my application, then gradle build gives me the following error:在 Java 应用程序 C 中,我正在实现库 A。如果我在我的应用程序中使用 CoolClass,那么gradle build会给我以下错误:

/ApplicationC/src/main/java/com/sorry/CoolClass.java:10: error: cannot access ExceptionB
                                           .someMethod();
                                                       ^
  class file for org.opensaml.core.xml.io.ExceptionB not found

Is there a way to pass just that exception rather than including the entire library in the class path of my application?有没有办法只传递该异常,而不是将整个库包含在我的应用程序的 class 路径中?

Not really, but your plan ('include just this one thing') is the wrong solution.不是真的,但你的计划(“只包括这件事”)是错误的解决方案。

The general principle you've run into is 'transitive dependencies'.您遇到的一般原则是“传递依赖”。

Project A is dependent on project B. However, B in turn depends on C... so does A depend on C now?项目 A 依赖于项目 B。但是,B 又依赖于 C ... 那么 A 现在是否依赖于 C?

transitive dependencies come in two 'flavours': Exported and non-exported.传递依赖有两种“风格”:导出的和非导出的。

Project B is a whole bunch of code, but crucially, some of that code is 'visible'.项目 B 是一大堆代码,但至关重要的是,其中一些代码是“可见的”。 Specifically, the public signatures .具体来说,公开签名

If project B's API (which A can see) includes, say, public List<String> getNames() , that means that the List dependency is now something A also needs to have, otherwise it can't interact with this method at all.如果项目 B 的 API (A 可以看到)包括public List<String> getNames() ,这意味着 List 依赖现在也是 A 需要的,否则它根本无法与此方法交互。 Fortunately, List is java.util.List which everybody always haves so that wouldn't be a problem, but imagine it's a type from something not in the java.* space.幸运的是, List 是java.util.List ,每个人都有,所以这不是问题,但想象一下它不是java.*空间中的类型。 To make this work, you export .为了使这项工作,您导出. And, it means that anytime you use any type from one of your dependencies in one of your public signatures, you have now forced that dependency to be exported .而且,这意味着无论何时您在一个公共签名中使用您的依赖项之一中的任何类型,您现在都已强制导出该依赖项。

That's what you've done here, by declaring throws SomethingSpecificFromOpenSAML , you must now export openSAML.这就是您在这里所做的,通过声明throws SomethingSpecificFromOpenSAML ,您现在必须导出 openSAML。

Solution: Just.. don't throw that解决方案:只是..不要扔那个

If that's the one and only thing you use in a public signature, the answer seems very obvious.如果这是您在公共签名中唯一使用的东西,那么答案似乎很明显。 Stop throwing that, your code is just wrong.别再扔了,你的代码是错误的。 You should not declare in your throws statement anything that's an implementation detail, and if you have no intention of 'exporting' OpenSAML here, then clearly it's an implementation detail.您不应在throws语句中声明任何实现细节,如果您无意在此处“导出”OpenSAML,那么显然它是一个实现细节。

Instead, catch it and throw it as something else.相反,抓住它并将其作为其他东西扔掉。 Or, keep it as is, but declare to throw Exception:或者,保持原样,但声明抛出异常:

// Example 1
public void saveGame() throws OpenSamlException {
  doSamlStuffHere();
}

// Example 2
public void saveGame() throws Exception {
  doSamlStuffHere();
}

// Example 3
public class SaveException extends Exception {
  public SaveException(String msg, Throwable cause) {
    super(msg, cause);
  }
}

public void saveGame() throws SaveException {
  try {
    doSamlStuffHere();
  } catch (OpenSamlException e) {
    throw new SaveException("Saving game " + getSaveName() + " failed", e);
  }
}

Example 1 is what you have now and it exports the idea of OpenSaml conceptually by explicitly naming it in the 'visible' part of the method (which is just its signature).示例 1 就是您现在所拥有的,它通过在方法的“可见”部分(这只是它的签名)中显式命名它来从概念上导出 OpenSaml 的想法。

Example 2 fixes that by naming java.lang.Exception .示例 2 通过命名java.lang.Exception解决了这个问题。 It also takes away the ability to meaningfully interact with the problem as thrown ( catch (Exception e) catches rather a lot), so it's a bit ugly.它还剥夺了与抛出的问题进行有意义交互的能力( catch (Exception e)捕获了很多),所以它有点难看。 But it solves the problem.但它解决了问题。

Example 3 is 'correct': It fully hides SAML as an implementation detail (nothing publicly visible shows anything about SAML at all, just like Example 2), but it does let you interact specifically with the problem, by rethrowing it as an exception that is still specific.示例 3 是“正确的”:它将 SAML 作为实现细节完全隐藏(没有任何公开可见的内容显示有关 SAML 的任何内容,就像示例 2 一样),但它确实让您可以专门与问题进行交互,将其重新抛出为异常还是具体的。 I'm using 'save a game' here just as example.我在这里使用“保存游戏”作为示例。

Example 2 and 3 mean you no longer need to export your transitive dependency.示例 2 和 3 意味着您不再需要导出传递依赖项。

Transitive dependencies do need to be on the classpath传递依赖确实需要在类路径上

Exported transitive dependencies need to be available as you compile (and write) the code.在编译(和编写)代码时,导出的传递依赖项需要可用。 And, of course, that dep needs to be on the classpath when you run the code.当然,当您运行代码时,该 dep 需要位于类路径中。

Non-exported transitive dependencies don't need to exist at all when you compile/write.编译/编写时根本不需要存在非导出的传递依赖项。 But they still need to be on the classpath when you run the code, obviously.但是很明显,当您运行代码时,它们仍然需要位于类路径中。 After all, you need SAML to exist in order to run your saveGame() method.毕竟,您需要存在 SAML 才能运行saveGame()方法。 You can't wish that away.你不能希望它消失。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何将数据从.Net Web应用程序传递到Java Applet - How can I pass data from a .Net Web Application to my Java Applet 如何从Java应用程序访问我的Gmail电子邮件? - How can I access my gmail emails from a Java application? "如何从 Java 8 流中抛出 CHECKED 异常?" - How can I throw CHECKED exceptions from inside Java 8 streams? 如何在编写库(而不是应用程序)时处理异常 - Java - How to handle exceptions when writing a library (not an application) - Java 如何在启动时将我的java应用程序(如.exe)传递给文档的路径? - How can pass my java application (as .exe) the path of a document on startup? 如何在Java应用程序中使用Python库? - How do I use a Python library in my Java application? 如何在Java Web应用程序中从JSP引用JavaScript库? - How can I reference a javascript library from a JSP in a java web application? 如何将ImageJ用作单独Java应用程序的库? - How can I use ImageJ as a library for a separate Java application? 如何在Java中自定义自定义异常? - How can I customize custom exceptions in Java? 如何确保Java Play应用程序仅接受来自特定主机的HTTP请求? - How do I ensure my Java Play application only accepts HTTP requests from a particular host?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM