1

I created a custom exception class and put it inside src/org/team/pipeline/TestResultFailed.groovy:

package org.team.pipeline

public class TestResultFailed extends Exception {
  // Parameterless Constructor
  public TestResultFailed() {}

  // Constructor that accepts a message
  public TestResultFailed(String message) {
    super(message);
  }
}

The only issue is the class (and thus even exception) cannot be easily imported from shared library to Jenkins pipeline. Therefore, it's not possible to directly throw exception from Jenkins pipeline. To bypass that, I tried to "wrap" my new exception into shared library function in vars/teamUtils.groovy:

import org.team.pipeline.*

def getTestResultFailedClass() {
    return TestResultFailed
}

And then I import and use it in Jenkinsfile as follows:

TestResultFailed = teamUtils.getTestResultFailedClass()

try {
    throw new TestResultFailed.TestResultFailed("error")
} catch (TestResultFailed err) {
    log.info("Exception caught: ${err}")
}

However, I get this error:

unable to resolve class TestResultFailed.TestResultFailed 

and no matter what I tried I'm still getting this error. Any help is very appreciated.

anechkayf
  • 481
  • 1
  • 4
  • 12
  • 1
    So in the pipeline script `import org.team.pipeline.*` doesn't work? IMO it should. What kind of error message do you get? – zett42 Feb 10 '23 at 08:08
  • @zett42 If I add `import org.team.pipeline.*` in the Jenkinsfile, I still get the same error `unable to resolve class TestResultFailed.TestResultFailed` – anechkayf Feb 10 '23 at 14:35
  • I'm using classes in pipeline without issues. This should work: `throw new TestResultFailed("error")`. I think the problem is that you try to explicitly call the constructor. – zett42 Feb 10 '23 at 14:38
  • @zett42 that doesn't work either, same error. How do you use the shared lib class directly in pipeline? – anechkayf Feb 10 '23 at 14:47
  • My pipelines are in the same shared library as the classes. There I just put an `import` statement at the top, as written above. But I just wrote a simple pipeline directly into the script section of a job, added the following two lines at the top `@Library('MyLibName')` and `import com.MyCompany.*` which enabled me to write `def test = new MyClass()` in a `script` step of the pipeline. – zett42 Feb 10 '23 at 15:03
  • In some examples you see `@Library('MyLibName') _` (underscore is annotated instead of `import`). This is not recommended when using classes as you have to prefix the full package path when referring to a class: `new org.team.pipeline.TestResultFailed("message")` – zett42 Feb 10 '23 at 15:08
  • @zett42 I've tried all these but nothing works :( Directly using this class in Jenkinsfile is not working. In the past, we've created a new enum class and then used the same logic of "wrapping" the class in `vars` and then importing to Jenkinsfile using this `vars` function, and it works. I'm doing exactly the same here, and it fails – anechkayf Feb 10 '23 at 17:40
  • 1
    As a last resort, instead of returning the class from the `vars` script, you could try to instanciate the class by the `vars` script, so referencing the class would be confined to the shared library. In "vars/teamUtils.groovy": `def getTestResultFailed(String message) { return new TestResultFailed(message) }` and in jenkinsfile: `throw getTestResultFailed("some error")` – zett42 Feb 10 '23 at 17:52
  • @zett42 that worked! Thank you so much for your help! Now I can throw this custom exception from Jenkinsfile. Do you know by any chance how to catch it? – anechkayf Feb 10 '23 at 18:17
  • 1
    That could be a problem. I think I just found a way to fix your original workaround of returning the class from "teamUtils.groovy". Instead of using `new` to instanciate it in the jenkinsfile you have to do it like this: `throw TestResultFailed.newInstance("message")`. See https://stackoverflow.com/a/30223804/7571258 . I'm not sure if the `catch` statement needs a change too. Maybe you have to catch the base class `Exception` and then check its type. – zett42 Feb 10 '23 at 18:25
  • 1
    that works as well! Thanks a lot for these 2 great options! I'll try finding if there is any way to use `catch` to specifically catch TestResultFailed. But as a last resort I could use a base class `Exception` and check its type as you proposed. – anechkayf Feb 10 '23 at 18:45

0 Answers0