Elasticsearch: NullPointerException when creating a watch with Jira action

Created on 7 May 2019  路  19Comments  路  Source: elastic/elasticsearch

CC @jakelandis

I'm able to reproduce this on master. I've configured the secure URL, user, and password all as "test". Here's the request I send:

PUT _xpack/watcher/watch/test
{
  "trigger": {
    "schedule": {
      "interval": "1h"
    }
  },
  "input": {
    "simple": {}
  },
  "actions": {
    "my_jira_action": {
      "jira": {
      }
    }
  }
}

Response:

{
  "error": {
    "root_cause": [
      {
        "type": "null_pointer_exception",
        "reason": null
      }
    ],
    "type": "null_pointer_exception",
    "reason": null
  },
  "status": 500
}

Stack trace:

[2019-05-07T14:44:38,870][WARN ][r.suppressed             ] [cj.attlocal.net] path: /_xpack/watcher/watch/test, params: {pretty=, id=test}
java.lang.NullPointerException: null
    at org.elasticsearch.xpack.watcher.common.http.Scheme.parse(Scheme.java:32) ~[?:?]
    at org.elasticsearch.xpack.watcher.notification.jira.JiraAccount.<init>(JiraAccount.java:64) ~[?:?]
    at org.elasticsearch.xpack.watcher.notification.jira.JiraService.createAccount(JiraService.java:66) ~[?:?]
    at org.elasticsearch.xpack.watcher.notification.jira.JiraService.createAccount(JiraService.java:26) ~[?:?]
    at org.elasticsearch.xpack.watcher.notification.NotificationService.lambda$createAccounts$0(NotificationService.java:141) ~[?:?]
    at org.elasticsearch.common.util.LazyInitializable.maybeCompute(LazyInitializable.java:103) ~[elasticsearch-8.0.0-SNAPSHOT.jar:8.0.0-SNAPSHOT]
    at org.elasticsearch.common.util.LazyInitializable.getOrCompute(LazyInitializable.java:81) ~[elasticsearch-8.0.0-SNAPSHOT.jar:8.0.0-SNAPSHOT]
    at org.elasticsearch.xpack.watcher.notification.NotificationService.getAccount(NotificationService.java:120) ~[?:?]
    at org.elasticsearch.xpack.watcher.actions.jira.JiraActionFactory.parseExecutable(JiraActionFactory.java:30) ~[?:?]
    at org.elasticsearch.xpack.watcher.actions.jira.JiraActionFactory.parseExecutable(JiraActionFactory.java:16) ~[?:?]
    at org.elasticsearch.xpack.core.watcher.actions.ActionWrapper.parse(ActionWrapper.java:229) ~[x-pack-core-8.0.0-SNAPSHOT.jar:8.0.0-SNAPSHOT]
    at org.elasticsearch.xpack.core.watcher.actions.ActionRegistry.parseActions(ActionRegistry.java:61) ~[x-pack-core-8.0.0-SNAPSHOT.jar:8.0.0-SNAPSHOT]
    at org.elasticsearch.xpack.watcher.watch.WatchParser.parse(WatchParser.java:169) ~[x-pack-watcher-8.0.0-SNAPSHOT.jar:8.0.0-SNAPSHOT]
    at org.elasticsearch.xpack.watcher.watch.WatchParser.parse(WatchParser.java:124) ~[x-pack-watcher-8.0.0-SNAPSHOT.jar:8.0.0-SNAPSHOT]
    at org.elasticsearch.xpack.watcher.watch.WatchParser.parseWithSecrets(WatchParser.java:103) ~[x-pack-watcher-8.0.0-SNAPSHOT.jar:8.0.0-SNAPSHOT]
    at org.elasticsearch.xpack.watcher.transport.actions.put.TransportPutWatchAction.doExecute(TransportPutWatchAction.java:82) [x-pack-watcher-8.0.0-SNAPSHOT.jar:8.0.0-SNAPSHOT]
    at org.elasticsearch.xpack.watcher.transport.actions.put.TransportPutWatchAction.doExecute(TransportPutWatchAction.java:58) [x-pack-watcher-8.0.0-SNAPSHOT.jar:8.0.0-SNAPSHOT]
    at org.elasticsearch.xpack.watcher.transport.actions.WatcherTransportAction.doExecute(WatcherTransportAction.java:39) [x-pack-watcher-8.0.0-SNAPSHOT.jar:8.0.0-SNAPSHOT]
    at org.elasticsearch.action.support.TransportAction$RequestFilterChain.proceed(TransportAction.java:145) [elasticsearch-8.0.0-SNAPSHOT.jar:8.0.0-SNAPSHOT]
    at org.elasticsearch.xpack.security.action.filter.SecurityActionFilter.apply(SecurityActionFilter.java:123) [x-pack-security-8.0.0-SNAPSHOT.jar:8.0.0-SNAPSHOT]
    at org.elasticsearch.action.support.TransportAction$RequestFilterChain.proceed(TransportAction.java:143) [elasticsearch-8.0.0-SNAPSHOT.jar:8.0.0-SNAPSHOT]
    at org.elasticsearch.action.support.TransportAction.execute(TransportAction.java:121) [elasticsearch-8.0.0-SNAPSHOT.jar:8.0.0-SNAPSHOT]
    at org.elasticsearch.action.support.TransportAction.execute(TransportAction.java:64) [elasticsearch-8.0.0-SNAPSHOT.jar:8.0.0-SNAPSHOT]
    at org.elasticsearch.client.node.NodeClient.executeLocally(NodeClient.java:83) [elasticsearch-8.0.0-SNAPSHOT.jar:8.0.0-SNAPSHOT]
    at org.elasticsearch.client.node.NodeClient.doExecute(NodeClient.java:72) [elasticsearch-8.0.0-SNAPSHOT.jar:8.0.0-SNAPSHOT]
    at org.elasticsearch.client.support.AbstractClient.execute(AbstractClient.java:394) [elasticsearch-8.0.0-SNAPSHOT.jar:8.0.0-SNAPSHOT]
    at org.elasticsearch.xpack.core.watcher.client.WatcherClient.putWatch(WatcherClient.java:158) [x-pack-core-8.0.0-SNAPSHOT.jar:8.0.0-SNAPSHOT]
    at org.elasticsearch.xpack.watcher.rest.action.RestPutWatchAction.lambda$doPrepareRequest$0(RestPutWatchAction.java:64) [x-pack-watcher-8.0.0-SNAPSHOT.jar:8.0.0-SNAPSHOT]
    at org.elasticsearch.rest.BaseRestHandler.handleRequest(BaseRestHandler.java:113) [elasticsearch-8.0.0-SNAPSHOT.jar:8.0.0-SNAPSHOT]
    at org.elasticsearch.rest.DeprecationRestHandler.handleRequest(DeprecationRestHandler.java:62) [elasticsearch-8.0.0-SNAPSHOT.jar:8.0.0-SNAPSHOT]
    at org.elasticsearch.xpack.security.rest.SecurityRestFilter.handleRequest(SecurityRestFilter.java:69) [x-pack-security-8.0.0-SNAPSHOT.jar:8.0.0-SNAPSHOT]
    at org.elasticsearch.rest.RestController.dispatchRequest(RestController.java:240) [elasticsearch-8.0.0-SNAPSHOT.jar:8.0.0-SNAPSHOT]
    at org.elasticsearch.rest.RestController.tryAllHandlers(RestController.java:337) [elasticsearch-8.0.0-SNAPSHOT.jar:8.0.0-SNAPSHOT]
    at org.elasticsearch.rest.RestController.dispatchRequest(RestController.java:174) [elasticsearch-8.0.0-SNAPSHOT.jar:8.0.0-SNAPSHOT]
    at org.elasticsearch.http.AbstractHttpServerTransport.dispatchRequest(AbstractHttpServerTransport.java:320) [elasticsearch-8.0.0-SNAPSHOT.jar:8.0.0-SNAPSHOT]
    at org.elasticsearch.http.AbstractHttpServerTransport.handleIncomingRequest(AbstractHttpServerTransport.java:370) [elasticsearch-8.0.0-SNAPSHOT.jar:8.0.0-SNAPSHOT]
    at org.elasticsearch.http.AbstractHttpServerTransport.incomingRequest(AbstractHttpServerTransport.java:299) [elasticsearch-8.0.0-SNAPSHOT.jar:8.0.0-SNAPSHOT]
    at org.elasticsearch.http.netty4.Netty4HttpRequestHandler.channelRead0(Netty4HttpRequestHandler.java:66) [transport-netty4-client-8.0.0-SNAPSHOT.jar:8.0.0-SNAPSHOT]
    at org.elasticsearch.http.netty4.Netty4HttpRequestHandler.channelRead0(Netty4HttpRequestHandler.java:31) [transport-netty4-client-8.0.0-SNAPSHOT.jar:8.0.0-SNAPSHOT]
    at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:105) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
    at org.elasticsearch.http.netty4.Netty4HttpPipeliningHandler.channelRead(Netty4HttpPipeliningHandler.java:58) [transport-netty4-client-8.0.0-SNAPSHOT.jar:8.0.0-SNAPSHOT]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
    at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:102) [netty-codec-4.1.35.Final.jar:4.1.35.Final]
    at io.netty.handler.codec.MessageToMessageCodec.channelRead(MessageToMessageCodec.java:111) [netty-codec-4.1.35.Final.jar:4.1.35.Final]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
    at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:102) [netty-codec-4.1.35.Final.jar:4.1.35.Final]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
    at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:102) [netty-codec-4.1.35.Final.jar:4.1.35.Final]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
    at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:323) [netty-codec-4.1.35.Final.jar:4.1.35.Final]
    at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:297) [netty-codec-4.1.35.Final.jar:4.1.35.Final]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
    at io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:287) [netty-handler-4.1.35.Final.jar:4.1.35.Final]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
    at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1408) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
    at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:930) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
    at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
    at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:682) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
    at io.netty.channel.nio.NioEventLoop.processSelectedKeysPlain(NioEventLoop.java:582) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
    at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:536) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:496) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
    at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:906) [netty-common-4.1.35.Final.jar:4.1.35.Final]
    at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) [netty-common-4.1.35.Final.jar:4.1.35.Final]
    at java.lang.Thread.run(Thread.java:835) [?:?]
:CorFeatureWatcher >bug good first issue help wanted

Most helpful comment

@ojasgulati Take all the time that you need, and let us know if/how we can help.

All 19 comments

Pinging @elastic/es-core-features

The secure_url protocol setting needs to be set; we could give a nicer error message yes but addressing that is not going to be high priority. As such I am marking this as help wanted and good first issue.

I was able to dig a little deeper and I believe this exception is thrown whenever a secure_url value is provided which is in an unexpected format. In my case, I was providing the string test. Once I changed this to https://test.com, the request completed successfully.

Hello, @jasontedor @cjcenizal I am new to contributing in elasticsearch. I like to solve this issue. I was able to build the project but I don't know how to start. Can you please help me to get started. :)

Hi @ojasgulati! I haven't spent much time in the ES codebase, so please disregard my comments if a more knowledgable engineer steps in.

I believe the error originates on this line: https://github.com/elastic/elasticsearch/blob/master/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/notification/jira/JiraAccount.java#L64. I think a good solution would be to catch the NullPointerException and throw a SettingsException (see line 66 for an example) which states something along the lines of "invalid jira [" + name + "] account settings. url does not conform to uri generic syntax."

That is a good start. Yet, rather than catching a NullPointerException for control flow, we can address this earlier in a few different ways:

  • Scheme#parse should reject the null argument more explicitly, probably with Objects.requiresNonNull rather than implicitly when we try to dereference the value
  • we could check uri.getScheme() before invoking Scheme#parse and throw a URISyntaxException which is caught a little further down and wrapped into a better error message

@cjcenizal @jasontedor Thank you for your comments. I will look into the problem.

@cjcenizal How to set up a jira account? i am getting this

{"error":{"root_cause":[{"type":"illegal_argument_exception","reason":"no accounts of type [jira] configured. Please set up an account using the [xpack.notification.jira] settings"}],"type":"illegal_argument_exception","reason":"no accounts of type [jira] configured. Please set up an account using the [xpack.notification.jira] settings"},"status":400}

@ojasgulati Follow the instructions here for configuring ES with the Jira action: https://www.elastic.co/guide/en/elastic-stack-overview/current/actions-jira.html#configuring-jira

To reproduce my error, enter "test" for the secure_url settings. When you create a watch as described in the issue description, you'll be able to generate the error I encountered. Thanks for digging into this!

@cjcenizal I was able to reproduce your error thank you for help :)

@jasontedor @cjcenizal I was able to rectify the nullpointerexecption. I added a code snippet can you tell is this a correct way? Thanks btw :)

try { URI uri = new URI(url); Scheme protocol = Scheme.parse(Objects.requireNonNull(uri.getScheme())); if ((protocol == Scheme.HTTP) && (Booleans.isTrue(settings.get(ALLOW_HTTP_SETTING)) == false)) { throw new SettingsException("invalid jira [" + name + "] account settings. unsecure scheme [" + protocol + "]"); } this.url = uri; } catch (URISyntaxException | IllegalArgumentException | NullPointerException e) { throw new SettingsException( "invalid jira [" + name + "] account settings. invalid [" + SECURE_URL_SETTING.getKey() + "] setting", e); }

@ojasgulati That's not quite what I had in mind, since that's still using the NullPointerException for control flow. Rather I would move the check for nullness of uri.getScheme() into Scheme#parse itself (so that it is explicitly validating its parameters); this method could use a Javadoc too. Further, I would check the nullness of uri.getScheme() before invoking Scheme#parse and throw a URISyntaxException if this is null.

Also, it would be easier to iterate if you opened a PR at this point, we can leave review comments there and it's easier to read the code. 馃槆

@ojasgulati I left review comments on your commits.
It will be easier to review your code if you submit a PR as @jasontedor suggested

@ojasgulati When you're ready to create a Pull Request (PR), you just need to create a new branch and push it to your fork. Then you can create a PR here. More info is in our CONTRIBUTING.md "Submitting your changes" section.

@jasontedor @ielatif @cjcenizal thank you all. I am new to open source projects that's why it took a lot of time :P

@ojasgulati Take all the time that you need, and let us know if/how we can help.

Is this still an open issue?

It looks like this should have been closed when https://github.com/elastic/elasticsearch/pull/42081 was merged, so I'm going to close it now - please comment on this issue if you see this behavior in 7.2.0 or later.

Was this page helpful?
0 / 5 - 0 ratings