GithubHelp home page GithubHelp logo

gerrit-events's Introduction

Gerrit Events

This is a Java library used primarily to listen to stream-events from Gerrit Code Review and to send reviews via the SSH CLI or the REST API. It was originally a module in the Jenkins Gerrit Trigger plugin and is now broken out to be used in other tools without the dependency to Jenkins.

Most of the development will still target the Jenkins plugin, but now it can also be used elsewhere.

Maven Central

Maintainers

Usage

A "real life" example of usage can be found in the Jenkins Plugin.

Start by creating a connection, attach some utility listeners and a GerritHandler.

connection = new GerritConnection(name, config);
GerritHandler handler = new GerritHandler();
handler.setIgnoreEMail(name, config.getGerritEMail());
connection.setHandler(handler);
connection.addListener(gerritConnectionListener);
connection.start();

The handler handles the event routing and a thread pool to try to keep up with the potentially huge amount of events coming from Gerrit. One handler can route from several connections.

Then create your event listener. The GerritEventListener interface requires you to implement one method called gerritEvent that takes a parameter of type GerritEvent which is the base class for all events. You can implement any number of gerritEvent methods that takes more specific event classes as its one parameter. The handler will use reflection to try to find the most suitable method to call and will fall back to the generic one if it can't find any.

public class MyEventListener implements GerritEventListener {
    @Override
    public void gerritEvent(GerritEvent event) {
        //Do something...
    }

    public void gerritEvent(PatchsetCreated event) {
        //Do something when someone uploads a patchset...
    }
}
handler.addListener(new MyEventListener());

All event types can be found in the com.sonymobile.tools.gerrit.gerritevents.dto.events package.

Environments

  • linux
    • java-1.8
      • maven-3.5.4

Java 8 & 9: Works.

The maintainers' development, tests and production environments are Ubuntu 12.04 so we have no means of detecting or fixing any Windows issues, but there are no specific reasons why it shouldn't run on Windows and some kind contributors provide win fixes every now and then.

Discarding events

You can create a whitelist of projects from which you want to consider events from. This will prevent operations on projects that you do not wish to view events from taking up resources. This is especially useful when a large Gerrit server is used and you are only trying to evaluate events for a small subset of projects.

You can set where the file is expected by setting the environment variable gerrit.whitelist.location to the file location.

An example file:

#simple txt file with each project on newline
foo

This will result in only events from the foo project being evaluated further.

The file can be updated and is polled every 30 minutes by default. This polling interval can be set with gerrit.whitelist.timeout.

Build

You build using maven

mvn clean package

Run findbugs for future reference or to make sure you haven't introduced any new warnings

mvn findbugs:findbugs

License

The MIT License

Copyright 2010 Sony Ericsson Mobile Communications. All rights reserved.
Copyright 2012 Sony Mobile Communications AB. All rights reserved.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

gerrit-events's People

Contributors

apetres avatar chgeo avatar christoffer-cortes avatar defer avatar dependabot[bot] avatar dpursehouse avatar gluck avatar glundh avatar howardlyliao avatar hugares avatar jakohbae avatar jeblair avatar jimilian avatar jyrkiput avatar kukido avatar mathieu-wang avatar mattlud avatar mawinter69 avatar mobangjack avatar olamy avatar orgads avatar rinrinne avatar rsandell avatar seware avatar slawekjaranowski avatar ssbarnea avatar sselberg avatar tkawachi avatar twestling avatar zaro0508 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gerrit-events's Issues

Found starting '{' but missing '}' at the end.

I use Gerrit-2.14.1, plugin events-log is also in the same version.
What I receive on jenkins:

INFO: Gerrit Plugin events-log is installed
Jun 28, 2017 7:56:24 AM com.sonymobile.tools.gerrit.gerritevents.GerritJsonEventFactory getJsonObjectIfInterestingAndUsable
WARNING: Unanticipated error when examining JSON String
net.sf.json.JSONException: Found starting '{' but missing '}' at the end. at character 0 of null
at net.sf.json.util.JSONTokener.syntaxError(JSONTokener.java:499)
at net.sf.json.util.JSONTokener.(JSONTokener.java:85)
at net.sf.json.JSONObject._fromString(JSONObject.java:1145)
at net.sf.json.JSONObject.fromObject(JSONObject.java:162)
at net.sf.json.JSONSerializer.toJSON(JSONSerializer.java:139)
at net.sf.json.JSONSerializer.toJSON(JSONSerializer.java:103)
at net.sf.json.JSONSerializer.toJSON(JSONSerializer.java:84)
at com.sonymobile.tools.gerrit.gerritevents.GerritJsonEventFactory.getJsonObjectIfInterestingAndUsable(GerritJsonEventFactory.java:126)
at com.sonyericsson.hudson.plugins.gerrit.trigger.playback.GerritMissedEventsPlaybackManager.createEventsFromString(GerritMissedEventsPlaybackManager.java:327)
at com.sonyericsson.hudson.plugins.gerrit.trigger.playback.GerritMissedEventsPlaybackManager.getEventsFromDateRange(GerritMissedEventsPlaybackManager.java:311)
at com.sonyericsson.hudson.plugins.gerrit.trigger.playback.GerritMissedEventsPlaybackManager.connectionEstablished(GerritMissedEventsPlaybackManager.java:197)
at com.sonymobile.tools.gerrit.gerritevents.GerritConnection.notifyListeners(GerritConnection.java:699)
at com.sonymobile.tools.gerrit.gerritevents.GerritConnection.notifyConnectionEstablished(GerritConnection.java:726)
at com.sonymobile.tools.gerrit.gerritevents.GerritConnection.run(GerritConnection.java:399)

Topic Changed Event does not propagate patch set

Hello,

When a topic changed event is triggered the event does not contain a patchset:

Aug 09 15:29:29 nc jenkins[886]: 2022-08-09 13:29:29.872+0000 [id=332]        INFO        c.s.h.p.g.t.g.ToGerritRunListener#onTriggered: Project [VersionBumpJenkins] triggered by Gerrit: [com.sonymobile.tools.gerrit.gerritevents.dto.events.TopicChanged@45c6eec8]
Aug 09 15:29:29 nc jenkins[886]: 2022-08-09 13:29:29.873+0000 [id=332]        INFO        c.s.h.p.g.t.h.EventListener#schedule: Project VersionBumpJenkins Build Scheduled: true By event: 542081
Aug 09 15:29:37 nc jenkins[886]: 2022-08-09 13:29:37.244+0000 [id=22014]        INFO        c.s.h.p.g.t.g.ToGerritRunListener#onStarted: Gerrit build [VersionBumpJenkins #11] Started for cause: [GerritCause: com.sonymobile.tools.gerrit.gerritevents.dto.events.TopicChanged@45c6eec8 silent: false].
Aug 09 15:29:37 nc jenkins[886]: 2022-08-09 13:29:37.244+0000 [id=22014]        INFO        c.s.h.p.g.t.g.ToGerritRunListener#onStarted: MemoryStatus:
Aug 09 15:29:37 nc jenkins[886]:   Project/Build: [VersionBumpJenkins]: [#11: null] Completed: false
Aug 09 15:29:38 nc jenkins[886]: 2022-08-09 13:29:38.640+0000 [id=19668]        SEVERE        c.s.t.g.g.w.c.AbstractSendCommandJob#sendCommand: Could not run command gerrit review 542081,<PATCHSET> --message 'Build Started http://192.168.178.22:8080/job/VersionBumpJenkins/11/ ' --verified 0 --code-review 0 --tag autogenerated:jenkins-gerrit-trigger
Aug 09 15:29:38 nc jenkins[886]: com.sonymobile.tools.gerrit.gerritevents.ssh.SshException: fatal: "542081,<PATCHSET>" is not a valid patch set (1)

This causes the our jenkins to being unable to send messages to gerrit changes where the topic was changed.

Handling both SSH & HTTP?

Hello!

We want to add a functionality where gerrit events plugin retrieves data both through ssh and http.

We have 2 possible solutions for this:

  1. Transform fromJson function in GerritJsonDTO into fromJsonSSH and fromJsonHTTP
    Modify Account, Approval, Change, Comment, PatchSet, Provider, RefUpdate classes accordingly
    Transform GerritQueryHandler class to GerritQueryHandlerSSH and add GerritQueryHandlerHTTP class (with a
    common QueryHandler interface)
    Adapt the remaining necessary changes

  2. Leave gerrit events as it is and make a converter for http json to ssh json (the json returned
    by the rest api is very different in structure to the one returned by ssh)

    Here is an example of a json returned by ssh

   {  
   "project":"project",
   "branch":"master",
   "id":"123123123123",
   "number":123,
   "subject":"Subject",
   "owner":{  
      "name":"name",
      "email":"email",
      "username":"username"
   },
   "url":"url",
   "commitMessage":"commitMessage",
   "createdOn":1537137142,
   "lastUpdated":1535770916,
   "open":true,
   "status":"NEW",
   "trackingIds":[  
      {  
         "system":"system",
         "id":"id"
      }
   ],
   "currentPatchSet":{  
      "number":11,
      "revision":"revision",
      "parents":[  
         "parents"
      ],
      "ref":"refs",
      "uploader":{  
         "name":"uploader",
         "username":"username"
      },
      "createdOn":1537137142,
      "author":{  
         "name":"name",
         "email":"email",
         "username":"username"
      },
      "kind":"kind",
      "approvals":[  
         {  
            "type":"Validated",
            "description":"Validated",
            "value":"1",
            "grantedOn":1885459715,
            "by":{  
               "name":"name",
               "username":"username"
            }
         },
         {  
            "type":"Code-Review",
            "description":"Code-Review",
            "value":"1",
            "grantedOn":1888644041,
            "by":{  
               "name":"name",
               "username":"username"
            }
         }
      ],
      "sizeInsertions":sizeInsertions,
      "sizeDeletions":-sizeDeletions
        }
    }
    ```

    And here is an example of a json containing the same information, returned by http 

    ```
    {
    "id": "id",
    "project": "project",
    "branch": "master",
    "hashtags": [],
    "change_id": "change_id",
    "subject": "Subject",
    "status": "NEW",
    "created": "2017-04-06 10:05:42.574000000",
    "updated": "2019-02-14 08:21:56.634000000",
    "submit_type": "submit_type",
    "mergeable": true,
    "insertions": insertions,
    "deletions": deletions,
    "unresolved_comment_count": 0,
    "has_review_started": true,
    "_number": number,
    "owner": {
      "_account_id": _account_id,
      "name": "name",
      "email": "email",
      "username": "username"
    },
    "labels": {
      "Verified": {
        "all": [
          {
            "value": 0,
            "permitted_voting_range": {
              "min": -1,
              "max": 2
            },
            "_account_id": _account_id,
            "name": "name",
            "username": "username"
          },
          {
            "value": 0,
            "permitted_voting_range": {
              "min": -1,
              "max": 2
            },
            "_account_id": _account_id,
            "name": "name",
            "email": "email",
            "username": "username"
          }
        ],
        "values": {
          "-1": "Fails",
          " 0": "No score",
          "+1": "Formatting is ok",
          "+2": "Build pass with associated unit tests"
        },
        "default_value": 0
      },
      "Code-Review": {
        "all": [
          {
            "value": 0,
            "permitted_voting_range": {
              "min": -2,
              "max": 2
            },
            "_account_id": _account_id,
            "name": "name",
            "username": "username"
          },
          {
            "value": 0,
            "permitted_voting_range": {
              "min": -2,
              "max": 1
            },
            "_account_id": _account_id,
            "name": "name",
            "email": "email",
            "username": "username"
          }
        ],
        "values": {
          "-2": "This shall not be merged",
          "-1": "I would prefer this is not merged as is",
          " 0": "No score",
          "+1": "Looks good to me, but someone else must approve",
          "+2": "Looks good to me, approved"
        },
        "default_value": 0
      },
      "Validated": {
        "all": [
          {
            "value": 0,
            "date": "2017-04-14 08:21:56.634000000",
            "permitted_voting_range": {
              "min": -2,
              "max": 2
            },
            "_account_id": _account_id,
            "name": "name",
            "username": "username"
          },
          {
            "value": 0,
            "permitted_voting_range": {
              "min": -2,
              "max": 1
            },
            "_account_id": _account_id,
            "name": "name",
            "email": "email",
            "username": "username"
          }
        ],
        "values": {
          "-2": "Failed to validate",
          "-1": "Failed to validate tests",
          " 0": "No score",
          "+1": "Passed validation",
          "+2": "Passed validation tests"
        },
        "default_value": 0
      },
      "Priority": {
        "all": [
          {
            "value": 0,
            "permitted_voting_range": {
              "min": -2,
              "max": 1
            },
            "_account_id": _account_id,
            "name": "name",
            "username": "username"
          },
          {
            "value": 0,
            "date": "2017-08-06 10:05:42.574000000",
            "permitted_voting_range": {
              "min": -2,
              "max": 1
            },
            "_account_id": _account_id,
            "name": "name",
            "email": "email",
            "username": "username"
          }
        ],
        "values": {
          "-2": "Blocker",
          "-1": "Critical",
          " 0": "No Priority",
          "+1": "Minor"
        },
        "default_value": 0,
        "optional": true
      }
    },
    "permitted_labels": {
      "Verified": [
        "-1",
        " 0",
        "+1",
        "+2"
      ],
      "Code-Review": [
        "-2",
        "-1",
        " 0",
        "+1",
        "+2"
      ],
      "Validated": [
        "-2",
        "-1",
        " 0",
        "+1",
        "+2"
      ],
      "Priority": [
        "-2",
        "-1",
        " 0",
        "+1"
      ]
    },
    "removable_reviewers": [
      {
        "_account_id": _account_id,
        "name": "name",
        "username": "username"
      },
      {
        "_account_id": _account_id,
        "name": "name",
        "email": "email",
        "username": "username"
      }
    ],
    "reviewers": {
      "REVIEWER": [
        {
          "_account_id": _account_id,
          "name": "name",
          "email": "email",
          "username": "username"
        },
        {
          "_account_id": _account_id,
          "name": "name",
          "username": "username"
        }
      ]
    },
    "pending_reviewers": {},
    "current_revision": "current_revision",
    "revisions": {
      "revisions": {
        "kind": "NO_CODE_CHANGE",
        "_number": 7,
        "created": "2017-04-08 13:14:33.349000000",
        "uploader": {
          "_account_id": _account_id,
          "name": "name",
          "username": "username"
        },
        "ref": "refs",
        "fetch": {
          "ssh": {
            "url": "ssh://url",
            "ref": "refs"
          },
          "anonymous http": {
            "url": "url",
            "ref": "ref"
          },
          "http": {
            "url": "url",
            "ref": "ref"
          }
        },
        "description": "Edit commit message"
      }
    }
}

Let us know what is your feedback on this idea, and which one is more likely to get merged into the repo :)

PS: I saw the issue w/r/t the new architecture proposal, but we don't want to do something that big yet (#10)

Using the default value of timeout=0 when creating SSH connections might lead to threads stuck forever

Hi, this is a follow-up of my investigation related to an incident me and my team was hit yesterday after our Gerrit instance outage.

I described the whole story in Jenkins' bug tracker as it was Jenkins' Gerrit Trigger plugin which was affected by the issue. See JENKINS-33959 and my comment specifically.

I believe the root cause of the above issue comes from this library.

Long story short, when the timeout parameter is not specified the library uses the default value of 0 when creating SSH connections. This blocked the calling thread, potentially forever (it's still blocked 1 day after we noticed it).

As I mentioned in the Jenkins ticket:

As a general thought setting timeouts to 0 is almost always a bad practice, unless you really want to wait forever. In practical applications it's usually better to let it timeout and simply retry.

Add the ability to read the output and if interactive shells are disabled on Gerrit

The SshConnection successfully opens a connection to Gerrit, executes the command, and then on its first readLine() call, the stream returns null. The GerritConnection object then keeps connecting and disconnecting every second without actually showing any errors to the outside world (minus the connect and disconnect events). It would be nice to receive an error message when some servers return the following output:

  ssh -p 29418 sshusername@hostname

    ****    Welcome to Gerrit Code Review    ****

    Hi John Doe, you have successfully connected over SSH.

    Unfortunately, interactive shells are disabled.
    To clone a hosted Git repository, use:

    git clone ssh://sshusername@hostname:29418/REPOSITORY_NAME.git

  Connection to hostname closed.

fast events create invalid JSON data

When the events are coming very fast, so that there are 2 newlines in the CharBuffer the getLine method is not properly splitting and creates corrupted data.
This is a simple missing break in the getLine.

CommentAdded events considered equal even if they are different comments

We are using the gerrit-trigger plugin as part of a setup at my company to trigger Jenkins builds on certain comments whenever a user would like additional builds performed on their change in Gerrit. For example, we should trigger build 1 when someone comments "requestBuild1" and build 2 when someone comments "requestBuild2". Build 1 sets a different label on the change than build 2 and so we do not want them merged (they have different "server" configurations to set the proper label). However, if a user comments "requestBuild1" and then immediately posts a separate comment with "requestBuild2", gerrit-trigger merges them together and the results of both will only be posted to 1 label.

The gerrit-trigger plugin should be smart enough to know that a comment added event on two different "servers", even if they point to the same Gerrit instance, should be handled separately. However, another issue that allows this is that the gerrit-events library's CommentAdded class considers 2 CommentAdded instances equal if the change and patchset of the two instances are the same, even if there were different comments that generated each one. CommentAdded events should be equal iff the change is the same, the patchset is the same, and the comment is the same.

How to use this library from other maven projects

This library still have not been deployed to any remote repositories. So we need to install own built package to local repository.

Do you have plan to deploy library package to remote maven repository?

Proposition of architecture.

I congratulate that you separate gerrit-events from jenkins plugins.
I know that this library mainly support gerrit events, but if you separate it, maybe you are interested to add some new feature.

My proposition is - create a few modules in gerrit-events project.

  • gerrit-objects - contains all gerrit JSON objects transformed to plain java object
  • gerrit-connections - interface for connection config, factory
  • gerrit-commands - gerrit abstract command impementation and command interface
  • gerrit-ssh - implementation of connections config, factory, commands and other which is connected with ssh protocol
  • gerrit-rest - implementation of connections config, factory, commands and other which is connected with rest/http protocol
  • gerrit-events - gerrit events implementation

Dependency in project should be:

  • gerrit-commands - depends on gerrit-connections, gerrit-objects
  • gerrit-shh - depends on gerrit-connections, gerrit-command, gerrit-objects
  • gerrit-rest - depends on gerrit-connections, gerrit-command, gerrit-objects
  • gerrit-events - depends on gerrit-connections, gerrit-objects, gerrit-ssh

Requirements:

  • method from commands and events return plain java object from gerrit-objects
  • connection factory can be extendable
  • modules depend on a minimum number of external libraries

Advantages:

  • minimum number of external dependency in other projects
  • using plain java object is simpler than using JSON object
  • commands are not dependent on protocol ssh / rest we have the same interface so we can easy change protocol in project

I can write:

GerritQuery query = new GerritSshQuery(new SSHConnectio(...))

in this case my project depends only on gerrit-ssh and some ssh implementation

I can also write:

GerritQuery query = new GerritRestQuery(new RestConnectio(...))

and in this case my project depends on gerrit-rest and some http connection library

Disadvantages:

  • there may be differences in the amount of commands for ssh and rest
  • there may be differences in the amount of returning data for ssh and rest

Test fails in some time.

One test

WatchTimeExceptionDataTest.testIsExceptionAtThisTimeMinutes 

fails in time 0:00 to 0:15

No support for ED25519 keys (replace JSCH library)

gerrit-events does not support ED25519 keys:

	com.sonymobile.tools.gerrit.gerritevents.ssh.SshException: com.jcraft.jsch.JSchException: invalid privatekey: [B@5e887fa3
		at com.sonymobile.tools.gerrit.gerritevents.ssh.SshConnectionImpl.connect(SshConnectionImpl.java:200)
		at com.sonymobile.tools.gerrit.gerritevents.ssh.SshConnectionFactory.getConnection(SshConnectionFactory.java:140)
		at com.sonymobile.tools.gerrit.gerritevents.ssh.SshConnectionFactory.getConnection(SshConnectionFactory.java:117)
		at com.sonymobile.tools.gerrit.gerritevents.GerritConnection.connect(GerritConnection.java:498)
		at com.sonymobile.tools.gerrit.gerritevents.GerritConnection.run(GerritConnection.java:404)
	Caused by: com.jcraft.jsch.JSchException: invalid privatekey: [B@5e887fa3
		at com.jcraft.jsch.KeyPair.load(KeyPair.java:664)
		at com.jcraft.jsch.KeyPair.load(KeyPair.java:561)
		at com.jcraft.jsch.IdentityFile.newInstance(IdentityFile.java:40)
		at com.jcraft.jsch.JSch.addIdentity(JSch.java:406)
		at com.jcraft.jsch.JSch.addIdentity(JSch.java:387)
		at com.sonymobile.tools.gerrit.gerritevents.ssh.SshConnectionImpl.connect(SshConnectionImpl.java:168)
		... 4 more

This is because the JSCH library does not.

Since JSCH seems not to be maintained anymore, it should be considered to switch to an alternative SSH library, e.g. Apache MINA.

Connections possibly left unclosed

Hi Team

We are using this library in one of the Jira PlugIns to connect to the Gerrit server to gather the reviwes information.

It looks like that in our environment library leaves some unclosed leftover connections which then affecting PlugIn functionality as server denies connection because of conn limit from Gerrit server side.

Is it possible that somewhere exception is not catched and connection left open?

2016-11-21 14:18:58,526 Caesium-1-4 DEBUG ServiceRunner [c.m.p.j.gerrit.multipleRepo.MultipleRepoConfigManagerImpl] ssh connection failed
com.sonymobile.tools.gerrit.gerritevents.ssh.SshException: com.jcraft.jsch.JSchException: SSH_MSG_DISCONNECT: 7 Too many concurrent connections
at com.sonymobile.tools.gerrit.gerritevents.ssh.SshConnectionImpl.connect(SshConnectionImpl.java:181)
at com.sonymobile.tools.gerrit.gerritevents.ssh.SshConnectionFactory.getConnection(SshConnectionFactory.java:98)
at com.sonymobile.tools.gerrit.gerritevents.ssh.SshConnectionFactory.getConnection(SshConnectionFactory.java:77)
at com.sonymobile.tools.gerrit.gerritevents.ssh.SshConnectionFactory.getConnection(SshConnectionFactory.java:59)
at com.meetme.plugins.jira.gerrit.multipleRepo.MultipleRepoConfigManagerImpl.createBareClone(MultipleRepoConfigManagerImpl.java:538)
at com.meetme.plugins.jira.gerrit.multipleRepo.MultipleRepoConfigManagerImpl.synchronize(MultipleRepoConfigManagerImpl.java:622)
at com.meetme.plugins.jira.gerrit.index.RevisionIndexer.updateIndexes(RevisionIndexer.java:223)
at com.meetme.plugins.jira.gerrit.scheduling.SynchronizerLauncher.execute(SynchronizerLauncher.java:36)
at com.atlassian.sal.jira.scheduling.JiraPluginScheduler$JobDescriptor.runJob(JiraPluginScheduler.java:110)
at com.atlassian.sal.jira.scheduling.JiraPluginScheduler.runJob(JiraPluginScheduler.java:80)
at com.atlassian.scheduler.core.JobLauncher.runJob(JobLauncher.java:153)
at com.atlassian.scheduler.core.JobLauncher.launchAndBuildResponse(JobLauncher.java:118)
at com.atlassian.scheduler.core.JobLauncher.launch(JobLauncher.java:97)
at com.atlassian.scheduler.caesium.impl.CaesiumSchedulerService.launchJob(CaesiumSchedulerService.java:443)
at com.atlassian.scheduler.caesium.impl.CaesiumSchedulerService.executeLocalJob(CaesiumSchedulerService.java:410)
at com.atlassian.scheduler.caesium.impl.CaesiumSchedulerService.executeQueuedJob(CaesiumSchedulerService.java:388)
at com.atlassian.scheduler.caesium.impl.CaesiumSchedulerService$1.consume(CaesiumSchedulerService.java:285)
at com.atlassian.scheduler.caesium.impl.CaesiumSchedulerService$1.consume(CaesiumSchedulerService.java:282)
at com.atlassian.scheduler.caesium.impl.SchedulerQueueWorker.executeJob(SchedulerQueueWorker.java:65)
at com.atlassian.scheduler.caesium.impl.SchedulerQueueWorker.executeNextJob(SchedulerQueueWorker.java:59)
at com.atlassian.scheduler.caesium.impl.SchedulerQueueWorker.run(SchedulerQueueWorker.java:34)
at java.lang.Thread.run(Thread.java:745)
Caused by: com.jcraft.jsch.JSchException: SSH_MSG_DISCONNECT: 7 Too many concurrent connections
at com.jcraft.jsch.Session.read(Session.java:987)
at com.jcraft.jsch.UserAuthPublicKey.start(UserAuthPublicKey.java:198)
at com.jcraft.jsch.Session.connect(Session.java:463)
at com.jcraft.jsch.Session.connect(Session.java:183)
at com.sonymobile.tools.gerrit.gerritevents.ssh.SshConnectionImpl.connect(SshConnectionImpl.java:177)
... 21 more

Regards,
Areg

Objects in package com.sonymobile.tools.gerrit.gerritevents.dto.events should have a Constructor with JSONObject as parameter

[2017-07-12 13:31:51 DEBUG] [Gerrit Worker EventThread_1] {com.sonymobile.tools.gerrit.gerritevents.GerritJsonEventFactory:73}-Constructor with JSONObject as parameter missing, trying default constructor.
java.lang.NoSuchMethodException: com.sonymobile.tools.gerrit.gerritevents.dto.events.CommentAdded.(net.sf.json.JSONObject)
at java.lang.Class.getConstructor0(Class.java:3082)
at java.lang.Class.getConstructor(Class.java:1825)
at com.sonymobile.tools.gerrit.gerritevents.GerritJsonEventFactory.getEvent(GerritJsonEventFactory.java:69)
at com.sonymobile.tools.gerrit.gerritevents.workers.AbstractJsonObjectWork.perform(AbstractJsonObjectWork.java:69)
at com.sonymobile.tools.gerrit.gerritevents.workers.StreamEventsStringWork.perform(StreamEventsStringWork.java:67)
at com.sonymobile.tools.gerrit.gerritevents.workers.EventThread.run(EventThread.java:66)

As you can see,because of the missing of Constructor with JSONObject as parameter,it will throw a lot of java.lang.NoSuchMethodException.

I am not sure the listener will work correctly in this case.But it make us confuse.

I hope someone can fix this.Of course,if I have time,I will try to do it as well.

e.....I hope that my poor english will not confuse you.I am a chinese.

[Refactor] Use data binding library

Now event data formatted by JSON is binded to event model by fromJSON(). It means that each event models have binding logic.

If we use data binding library like Jackson, we can get more simple event models like beans or pojo. It would allow us to follow the latest gerrit event model easily.

I created a study project. Please check the below if interested.
https://github.com/rinrinne/bind-event-sample

Gerrit Events not causing a trigger

We don't see the issue in #70 any longer, and we're not sure why, perhaps networking changes we are unaware of...
We have downgraded to Gerrit Trigger 2.23.3
But Events are still not triggering a Jenkins pipeline job consistently, the trigger typically stops during the night and we are having to restart the Jenkins server the next morning to get triggers working again.

We captured a heap dump this morning just before we did a Jenkins restart to get the triggers happening again on this same server. After the restart, triggers began to happen again.
Please analyze and let us know how we can help further.

I see this potential thread as suspect ???

"Connect thread gerrit.ericsson.se session" prio=5 tid=91 TIMED_WAITING
	at java.lang.Object.wait(Native Method)
	at java.io.PipedInputStream.awaitSpace(PipedInputStream.java:273)
	at java.io.PipedInputStream.receive(PipedInputStream.java:231)
	at java.io.PipedOutputStream.write(PipedOutputStream.java:149)
	at com.jcraft.jsch.Channel$PassiveOutputStream.write(Channel.java:660)
	at com.jcraft.jsch.IO.put(IO.java:64)
	   Local Variable: com.jcraft.jsch.IO#1
	at com.jcraft.jsch.Channel.write(Channel.java:438)
	at com.jcraft.jsch.Session.run(Session.java:1448)
	   Local Variable: int[]#9794
	   Local Variable: com.jcraft.jsch.Buffer#2
	   Local Variable: com.jcraft.jsch.Packet#2
	   Local Variable: int[]#9793
	   Local Variable: byte[]#32460
	   Local Variable: com.jcraft.jsch.Session#1
	at java.lang.Thread.run(Thread.java:745)

Heap Dump:
https://drive.google.com/file/d/0B533WzlrxWraWTZaOElXSGN5M1U/view?usp=sharing

How to detect if gerrit connection is alive?

I just wanted to know that after I make connection to the gerrit server, how can i find if the connection has really established or not. Sometimes when I run my program, if Gerrit has not started, I am not able to find that. Is there a way to do that after I try to establish a connection.

Deadlock when shutting down while establishing connection

I've noticed a deadlock when calling the GerritConnection.shutdown(true) method while establishing the connection in GerritConnection.run().

The deadlock sequence is like this:

Thread 1: calls GerritConnection.run() -> calls into connect() -> SshConnectionFactory.getConnection()
Thread 2: calls GerritConnection.shutdown(true), sshConnection is null at this point, doesn't call sshConnection.disconnect(), calls join()
Thread 1: returns from connect() call, sets sshConnection, continues up to read() and blocks
Thread 2: join() never returns as read() in Thread 1 blocks (sshConnection.disconnect() is not called before)

Below are the callstacks of the two threads (Thread 2 initiates the connection shutdown by executing a Jenkins script "io.jenkins.plugins.casc.ConfigurationAsCode.get().configure()", JCasC removes all Gerrit severs and adds them again).

Id=106 Group=main TIMED_WAITING on com.jcraft.jsch.Channel$MyPipedInputStream@686f0414
	at [email protected]/java.lang.Object.wait(Native Method)
	-  waiting on com.jcraft.jsch.Channel$MyPipedInputStream@686f0414
	at [email protected]/java.io.PipedInputStream.read(PipedInputStream.java:326)
	at [email protected]/java.io.PipedInputStream.read(PipedInputStream.java:377)
	at [email protected]/sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
	at [email protected]/sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
	at [email protected]/sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
	-  locked java.io.InputStreamReader@450eb826
	at [email protected]/java.io.InputStreamReader.read(InputStreamReader.java:181)
	at [email protected]/java.io.Reader.read(Reader.java:189)
	at com.sonymobile.tools.gerrit.gerritevents.GerritConnection.run(GerritConnection.java:434)

"Handling POST /scriptText from 172.17.0.4 : Jetty (winstone)-35" Id=35 Group=main WAITING on com.sonymobile.tools.gerrit.gerritevents.GerritConnection@28a5ee8e
	at [email protected]/java.lang.Object.wait(Native Method)
	-  waiting on com.sonymobile.tools.gerrit.gerritevents.GerritConnection@28a5ee8e
	at [email protected]/java.lang.Thread.join(Thread.java:1300)
	at [email protected]/java.lang.Thread.join(Thread.java:1375)
	at com.sonymobile.tools.gerrit.gerritevents.GerritConnection.shutdown(GerritConnection.java:710)
	at com.sonyericsson.hudson.plugins.gerrit.trigger.GerritServer.stopConnection(GerritServer.java:617)
	-  locked com.sonyericsson.hudson.plugins.gerrit.trigger.GerritServer@29949ddb
	at com.sonyericsson.hudson.plugins.gerrit.trigger.config.GerritJcascConfigurator.configure(GerritJcascConfigurator.java:95)
	at com.sonyericsson.hudson.plugins.gerrit.trigger.config.GerritJcascConfigurator.configure(GerritJcascConfigurator.java:57)
	at io.jenkins.plugins.casc.BaseConfigurator.configure(BaseConfigurator.java:277)
	at io.jenkins.plugins.casc.BaseConfigurator.configure(BaseConfigurator.java:360)
	at io.jenkins.plugins.casc.BaseConfigurator.configure(BaseConfigurator.java:283)
	at io.jenkins.plugins.casc.ConfigurationAsCode.lambda$configureWith$7(ConfigurationAsCode.java:823)
	at io.jenkins.plugins.casc.ConfigurationAsCode$$Lambda$561/0x0000000800ca8c40.apply(Unknown Source)
	at io.jenkins.plugins.casc.ConfigurationAsCode.invokeWith(ConfigurationAsCode.java:773)
	at io.jenkins.plugins.casc.ConfigurationAsCode.configureWith(ConfigurationAsCode.java:823)
	at io.jenkins.plugins.casc.ConfigurationAsCode.configureWith(ConfigurationAsCode.java:695)
	at io.jenkins.plugins.casc.ConfigurationAsCode.configure(ConfigurationAsCode.java:352)
	at io.jenkins.plugins.casc.ConfigurationAsCode$configure$0.call(Unknown Source)
	at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:120)
	at Script1.run(Script1.groovy:1)
	at groovy.lang.GroovyShell.evaluate(GroovyShell.java:574)
	at groovy.lang.GroovyShell.evaluate(GroovyShell.java:612)
	at groovy.lang.GroovyShell.evaluate(GroovyShell.java:583)
	at hudson.util.RemotingDiagnostics$Script.call(RemotingDiagnostics.java:149)
	at hudson.util.RemotingDiagnostics$Script.call(RemotingDiagnostics.java:118)
	at hudson.remoting.LocalChannel.call(LocalChannel.java:47)
	at hudson.util.RemotingDiagnostics.executeGroovy(RemotingDiagnostics.java:115)
	at jenkins.model.Jenkins._doScript(Jenkins.java:4869)
	at jenkins.model.Jenkins.doScriptText(Jenkins.java:4847)
	at [email protected]/java.lang.invoke.LambdaForm$DMH/0x00000008001ff440.invokeVirtual(LambdaForm$DMH)
	at [email protected]/java.lang.invoke.LambdaForm$MH/0x0000000800422040.invoke(LambdaForm$MH)
	at [email protected]/java.lang.invoke.LambdaForm$MH/0x00000008003f1440.invoke(LambdaForm$MH)
	at [email protected]/java.lang.invoke.Invokers$Holder.invokeExact_MT(Invokers$Holder)
	at [email protected]/java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:710)
	at org.kohsuke.stapler.Function$MethodFunction.invoke(Function.java:397)
	at org.kohsuke.stapler.Function$InstanceFunction.invoke(Function.java:409)
	at org.kohsuke.stapler.Function.bindAndInvoke(Function.java:207)
	at org.kohsuke.stapler.Function.bindAndInvokeAndServeResponse(Function.java:140)
	at org.kohsuke.stapler.MetaClass$11.doDispatch(MetaClass.java:558)
	at org.kohsuke.stapler.NameBasedDispatcher.dispatch(NameBasedDispatcher.java:59)
	at org.kohsuke.stapler.Stapler.tryInvoke(Stapler.java:770)
	at org.kohsuke.stapler.Stapler.invoke(Stapler.java:900)
	at org.kohsuke.stapler.Stapler.invoke(Stapler.java:698)
	at org.kohsuke.stapler.Stapler.service(Stapler.java:248)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:590)
	at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:764)
	at org.eclipse.jetty.servlet.ServletHandler$ChainEnd.doFilter(ServletHandler.java:1665)
	at hudson.util.PluginServletFilter$1.doFilter(PluginServletFilter.java:163)
	at hudson.security.HudsonPrivateSecurityRealm$2.doFilter(HudsonPrivateSecurityRealm.java:1022)
	at hudson.util.PluginServletFilter$1.doFilter(PluginServletFilter.java:160)
	at org.jenkinsci.plugins.ssegateway.Endpoint$SSEListenChannelFilter.doFilter(Endpoint.java:248)
	at hudson.util.PluginServletFilter$1.doFilter(PluginServletFilter.java:160)
	at hudson.plugins.locale.LocaleFilter.doFilter(LocaleFilter.java:39)
	at hudson.util.PluginServletFilter$1.doFilter(PluginServletFilter.java:160)
	at io.jenkins.blueocean.ResourceCacheControl.doFilter(ResourceCacheControl.java:134)
	at hudson.util.PluginServletFilter$1.doFilter(PluginServletFilter.java:160)
	at io.jenkins.blueocean.auth.jwt.impl.JwtAuthenticationFilter.doFilter(JwtAuthenticationFilter.java:60)
	at hudson.util.PluginServletFilter$1.doFilter(PluginServletFilter.java:160)
	at jenkins.util.HttpServletFilter$1.doFilter(HttpServletFilter.java:76)
	at hudson.util.PluginServletFilter$1.doFilter(PluginServletFilter.java:160)
	at hudson.util.PluginServletFilter.doFilter(PluginServletFilter.java:166)
	at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:202)
	at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1635)
	at jenkins.ErrorAttributeFilter.doFilter(ErrorAttributeFilter.java:29)
	at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:202)
	at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1635)
	at jenkins.security.ApiCrumbExclusion.process(ApiCrumbExclusion.java:48)
	at hudson.security.csrf.CrumbFilter.doFilter(CrumbFilter.java:128)
	at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:202)
	at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1635)
	at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:94)
	at jenkins.security.AcegiSecurityExceptionFilter.doFilter(AcegiSecurityExceptionFilter.java:52)
	at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:99)
	at hudson.security.UnwrapSecurityExceptionFilter.doFilter(UnwrapSecurityExceptionFilter.java:54)
	at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:99)
	at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:126)
	at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:120)
	at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:99)
	at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:100)
	at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:99)
	at org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter.doFilter(RememberMeAuthenticationFilter.java:110)
	at org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter.doFilter(RememberMeAuthenticationFilter.java:101)
	at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:99)
	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:227)
	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:221)
	at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:99)
	at jenkins.security.BasicHeaderProcessor.success(BasicHeaderProcessor.java:139)
	at jenkins.security.BasicHeaderProcessor.doFilter(BasicHeaderProcessor.java:86)
	at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:99)
	at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:117)
	at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
	at hudson.security.HttpSessionContextIntegrationFilter2.doFilter(HttpSessionContextIntegrationFilter2.java:63)
	at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:99)
	at hudson.security.ChainedServletFilter.doFilter(ChainedServletFilter.java:111)
	at hudson.security.HudsonFilter.doFilter(HudsonFilter.java:172)
	at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:202)
	at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1635)
	at org.kohsuke.stapler.compression.CompressionFilter.doFilter(CompressionFilter.java:53)
	at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:202)
	at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1635)
	at hudson.util.CharacterEncodingFilter.doFilter(CharacterEncodingFilter.java:86)
	at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:202)
	at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1635)
	at org.kohsuke.stapler.DiagnosticThreadNameFilter.doFilter(DiagnosticThreadNameFilter.java:30)
	at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:202)
	at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1635)
	at jenkins.security.SuspiciousRequestFilter.doFilter(SuspiciousRequestFilter.java:38)
	at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:202)
	at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1635)
	at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:527)
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:131)
	at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:569)
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:122)
	at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:223)
	at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1570)
	at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:221)
	at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1384)
	at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:176)
	at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:484)
	at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1543)
	at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:174)
	at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1306)
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:129)
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:122)
	at org.eclipse.jetty.server.Server.handle(Server.java:563)
	at org.eclipse.jetty.server.HttpChannel$RequestDispatchable.dispatch(HttpChannel.java:1598)
	at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:753)
	at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:501)
	at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:287)
	at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:314)
	at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:100)
	at org.eclipse.jetty.io.SelectableChannelEndPoint$1.run(SelectableChannelEndPoint.java:53)
	at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.runTask(AdaptiveExecutionStrategy.java:421)
	at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.consumeTask(AdaptiveExecutionStrategy.java:390)
	at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.tryProduce(AdaptiveExecutionStrategy.java:277)
	at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.run(AdaptiveExecutionStrategy.java:199)
	at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:411)
	at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:969)
	at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.doRunJob(QueuedThreadPool.java:1194)
	at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1149)
	at [email protected]/java.lang.Thread.run(Thread.java:829)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.