gitblit-org / gitblit

pure java git solution
http://gitblit.com
Apache License 2.0
2.27k stars 671 forks source link

Init failure on Gerrit plugin #1413

Open orgads opened 2 years ago

orgads commented 2 years ago

I'm trying to revive the gitblit plugin for Gerrit 3.5. I built it successfully, but when I'm trying to load it, I get the following exception:

com.google.gerrit.server.plugins.PluginInstallException: Unable to provision, see the following errors:

1) [Guice/ErrorInjectingConstructor]: NoClassDefFoundError: javax/activation/DataSource
  at NotificationManager.<init>(NotificationManager.java:55)
  at NotificationManager.class(NotificationManager.java:43)
  while locating NotificationManager
  at GitblitManager.<init>(GitblitManager.java:151)
      \_ for 5th parameter
  at GitblitManager.class(GitblitManager.java:108)
  while locating GitblitManager
  at GerritAuthFilter.<init>(GerritAuthFilter.java:43)
      \_ for 1st parameter gitBlit
  at GerritAuthFilter.class(GerritAuthFilter.java:43)
  at GerritWicketFilter.<init>(GerritWicketFilter.java:72)
      \_ for 2nd parameter gerritAuthFilter
  at GerritWicketFilter.class(GerritWicketFilter.java:49)
  while locating GerritWicketFilter

Learn more:
  https://github.com/google/guice/wiki/ERROR_INJECTING_CONSTRUCTOR

1 error

======================
Full classname legend:
======================
GerritAuthFilter:     "com.googlesource.gerrit.plugins.gitblit.auth.GerritAuthFilter"
GerritWicketFilter:   "com.googlesource.gerrit.plugins.gitblit.GerritWicketFilter"
GitblitManager:       "com.gitblit.manager.GitblitManager"
NotificationManager:  "com.gitblit.manager.NotificationManager"
========================
End of classname legend:
========================

I tried replacing NotificationManager contents with NoopNotificationManager, and it worked, so I guess it's something in the class implementation.

flaix commented 2 years ago

What Java version is this running on? This sounds like a problem that comes up with moving to Java 9 or higher. From Java 9 on some classes were not part of the JVE anymore and need to be included as an explicit dependency. That is why the dependency to com.sun.activation:javax.activation:1.2.0 was added. You may have to make sure that is present in your build.

orgads commented 2 years ago

Java 11. I have this dependency.

orgads commented 2 years ago

ping?

flaix commented 2 years ago

I would love to help, but I don't build the plugin or run a Gerrit instance. So I don't know how else to help. From experience and from the error message, it is a missing dependency that is not present in your server's runtime class path. I cannot think of anything else but to make sure that the java.activation JAR is preset in the class path that is used for the server.

flaix commented 2 years ago

Were you able to get more debug information or other information? Like check if the JAR is present at runtime?

orgads commented 2 years ago

I have a simple way to reproduce, if it helps. This is a jar I built with the change linked above, and latest gerrit 3.5: gitblit.zip.

Rename it to jar, then run:

docker run --rm -ti -p 8080:8080 -p 29418:29418 -v $PWD/gitblit.jar:/var/gerrit/plugins/gitblit.jar gerritcodereview/gerrit:3.5.1

This is the output I'm getting:

[2022-04-27T15:15:09.916Z] [main] WARN  com.googlesource.gerrit.plugins.replication.DestinationConfigParser : Replication config does not exist or it's empty; not replicating
[2022-04-27T15:15:09.936Z] [main] INFO  com.google.gerrit.server.plugins.PluginLoader : Loaded plugin replication, version v3.5.1
[2022-04-27T15:15:09.987Z] [main] INFO  com.google.gerrit.server.plugins.PluginLoader : Loaded plugin reviewnotes, version v3.5.1
[2022-04-27T15:15:10.009Z] [main] INFO  com.google.gerrit.server.plugins.PluginLoader : Loaded plugin singleusergroup, version v3.5.1
[2022-04-27T15:15:10.112Z] [main] INFO  com.google.gerrit.server.plugins.PluginLoader : Loaded plugin uploadvalidator, version v3.0.0-rc1-284-gefecf8cdf4
[2022-04-27T15:15:10.167Z] [main] INFO  com.google.gerrit.server.plugins.PluginLoader : Loaded plugin webhooks, version v3.5.1
[2022-04-27T15:15:10.177Z] [main] INFO  com.google.gerrit.server.config.ScheduleConfig : No schedule configuration for "accountDeactivation".
[2022-04-27T15:15:10.189Z] [WorkQueue-2[java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask@475bf443[Not completed, task = java.util.concurrent.Executors$RunnableAdapter@4da39f33[Wrapped task = com.google.gerrit.server.logging.LoggingContextAwareRunnable@436478f7]]]] INFO  com.googlesource.gerrit.plugins.deleteproject.fs.RepositoryCleanupTask : Cleaning up expired git repositories...
[2022-04-27T15:15:10.198Z] [WorkQueue-2[java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask@475bf443[Not completed, task = java.util.concurrent.Executors$RunnableAdapter@4da39f33[Wrapped task = com.google.gerrit.server.logging.LoggingContextAwareRunnable@436478f7]]]] INFO  com.googlesource.gerrit.plugins.deleteproject.fs.RepositoryCleanupTask : Cleaning up expired git repositories... Done
[2022-04-27T15:15:10.209Z] [main] INFO  com.google.gerrit.sshd.SshDaemon : Started Gerrit APACHE-SSHD-2.6.0 on *:29418
[2022-04-27T15:15:10.212Z] [main] INFO  org.eclipse.jetty.server.Server : jetty-9.4.36.v20210114; built: 2021-01-14T16:44:28.689Z; git: 238ec6997c7806b055319a6d11f8ae7564adc0de; jvm 11.0.14.1+1-LTS
[2022-04-27T15:15:10.245Z] [main] INFO  org.eclipse.jetty.server.session : DefaultSessionIdManager workerName=node0
[2022-04-27T15:15:10.246Z] [main] INFO  org.eclipse.jetty.server.session : No SessionScavenger set, using defaults
[2022-04-27T15:15:10.247Z] [main] INFO  org.eclipse.jetty.server.session : node0 Scavenging every 660000ms
[2022-04-27T15:15:10.451Z] [main] INFO  org.eclipse.jetty.server.session : node0 Stopped scavenging
[2022-04-27T15:15:10.453Z] [main] ERROR com.google.gerrit.pgm.Daemon : Unable to start daemon
java.lang.IllegalStateException: Cannot start HTTP daemon
        at com.google.gerrit.pgm.http.jetty.JettyServer$Lifecycle.start(JettyServer.java:109)
        at com.google.gerrit.lifecycle.LifecycleManager.start(LifecycleManager.java:95)
        at com.google.gerrit.pgm.Daemon.start(Daemon.java:386)
        at com.google.gerrit.pgm.Daemon.run(Daemon.java:285)
        at com.google.gerrit.pgm.util.AbstractProgram.main(AbstractProgram.java:61)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at com.google.gerrit.launcher.GerritLauncher.invokeProgram(GerritLauncher.java:224)
        at com.google.gerrit.launcher.GerritLauncher.mainImpl(GerritLauncher.java:120)
        at com.google.gerrit.launcher.GerritLauncher.main(GerritLauncher.java:65)
        at Main.main(Main.java:28)
Caused by: com.google.inject.ProvisionException: Unable to provision, see the following errors:

1) [Guice/ErrorInjectingConstructor]: NoClassDefFoundError: javax/activation/DataSource
  at NotificationManager.<init>(NotificationManager.java:55)
  at NotificationManager.class(NotificationManager.java:43)
  while locating NotificationManager
  at GitblitManager.<init>(GitblitManager.java:151)
      \_ for 5th parameter
  at GitblitManager.class(GitblitManager.java:108)
  while locating GitblitManager
  at GerritAuthFilter.<init>(GerritAuthFilter.java:43)
      \_ for 1st parameter gitBlit
  at GerritAuthFilter.class(GerritAuthFilter.java:43)
  at GerritWicketFilter.<init>(GerritWicketFilter.java:72)
      \_ for 2nd parameter gerritAuthFilter
  at GerritWicketFilter.class(GerritWicketFilter.java:49)
  while locating GerritWicketFilter

Learn more:
  https://github.com/google/guice/wiki/ERROR_INJECTING_CONSTRUCTOR

1 error

======================
Full classname legend:
======================
GerritAuthFilter:     "com.googlesource.gerrit.plugins.gitblit.auth.GerritAuthFilter"
GerritWicketFilter:   "com.googlesource.gerrit.plugins.gitblit.GerritWicketFilter"
GitblitManager:       "com.gitblit.manager.GitblitManager"
NotificationManager:  "com.gitblit.manager.NotificationManager"
========================
End of classname legend:
========================
flaix commented 1 year ago

How did you manage to build it? I tried to build the plugin, but it complains about downloading wicket-extensions from maven central. I cannot download the zip file you attached, so I tried to build it myself. What changed so that it can be built from the stock JAR, compared to previously?

Edit: Apparently it just needs to be executed a few times to correct itself. But now I am stuck at the build complaining about jgit

ERROR: /Users/florian/Devel/Tests/Gerrit/gerrit/WORKSPACE:107:17: fetching local_repository rule //external:jgit: java.io.IOException: No WORKSPACE file found in /private/var/tmp/_bazel_florian/992c15ad0c448f20077c9f60735f3ed5/external/jgit
ERROR: /Users/florian/Devel/Tests/Gerrit/gerrit/lib/BUILD:59:13: //lib:jgit-archive depends on @jgit//org.eclipse.jgit.archive:jgit-archive in repository @jgit which failed to fetch. no such package '@jgit//org.eclipse.jgit.archive': No WORKSPACE file found in /private/var/tmp/_bazel_florian/992c15ad0c448f20077c9f60735f3ed5/external/jgit
ERROR: Analysis of target '//plugins/gitblit:gitblit' failed; build aborted:
orgads commented 1 year ago

Do you have all the submodules checked out? Run git submodule update --init and retry building.

flaix commented 1 year ago

I take you build this on Linux? Because I am getting nowhere with macOS.

flaix commented 1 year ago

Well, as expected the resulting gitblit.jar plugin does not contain the javax.activation classes. You said you have this dependency? I got your branch but did not find it in the external_plugin_deps.bzl file.

Anyhow, if I add below patch, it builds and runs in Gerrit. Well, it starts. I have no idea how to see if it actually works then. You may want to apply the patch and try it in Gerrit.

diff --git a/BUILD b/BUILD
index 2593ebd..91d3db3 100644
--- a/BUILD
+++ b/BUILD
@@ -22,6 +22,7 @@ gerrit_plugin(
         "@groovy//jar",
         "@httpcore//jar:neverlink",
         "@ivy//jar",
+        "@javax-activation//jar",
         "@jdom//jar",
         "@libpam4j//jar",
         "@lucene-core//jar:neverlink",
diff --git a/external_plugin_deps.bzl b/external_plugin_deps.bzl
index cc73bca..86800b8 100644
--- a/external_plugin_deps.bzl
+++ b/external_plugin_deps.bzl
@@ -106,6 +106,12 @@ def external_plugin_deps():
     sha1 = '08210b4af6f055ada934753facd27d7abf9d01a8',
   )

+  maven_jar(
+    name = 'javax-activation',
+    artifact = 'com.sun.activation:javax.activation:1.2.0',
+    sha1 = 'bf744c1e2776ed1de3c55c8dac1057ec331ef744',
+  )
+
   maven_jar(
     name = 'ivy',
     artifact = 'org.apache.ivy:ivy:2.2.0',
flaix commented 1 year ago

While we are at it, is there a way for Gitblit to know that it runs as a Gerrit plugin?

orgads commented 1 year ago

@flaix Thanks for the hint. Looks better, but it now fails with another error:

[2022-11-20T15:20:07.406+02:00] [HTTP GET /review/plugins/gitblit/repositories/ (orgads from 10.1.2.3)] ERROR org.apache.wicket.RequestCycle : Can't instantiate page using constructor public com.gitblit.wicket.pages.RepositoriesPage()
org.apache.wicket.WicketRuntimeException: Can't instantiate page using constructor public com.gitblit.wicket.pages.RepositoriesPage()
    at org.apache.wicket.session.DefaultPageFactory.createPage(DefaultPageFactory.java:212)
    at org.apache.wicket.session.DefaultPageFactory.newPage(DefaultPageFactory.java:57)
    at org.apache.wicket.request.target.component.BookmarkablePageRequestTarget.newPage(BookmarkablePageRequestTarget.java:298)
    at org.apache.wicket.request.target.component.BookmarkablePageRequestTarget.getPage(BookmarkablePageRequestTarget.java:320)
    at org.apache.wicket.request.target.component.BookmarkablePageRequestTarget.processEvents(BookmarkablePageRequestTarget.java:234)
    at org.apache.wicket.request.AbstractRequestCycleProcessor.processEvents(AbstractRequestCycleProcessor.java:92)
    at org.apache.wicket.RequestCycle.processEventsAndRespond(RequestCycle.java:1279)
    at org.apache.wicket.RequestCycle.step(RequestCycle.java:1358)
    at org.apache.wicket.RequestCycle.steps(RequestCycle.java:1465)
    at org.apache.wicket.RequestCycle.request(RequestCycle.java:545)
    at org.apache.wicket.protocol.http.WicketFilter.doGet(WicketFilter.java:486)
    at org.apache.wicket.protocol.http.WicketFilter.doFilter(WicketFilter.java:319)
    at com.googlesource.gerrit.plugins.gitblit.GerritWicketFilter.doFilter(GerritWicketFilter.java:128)
    at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:82)
    at com.google.inject.servlet.ManagedFilterPipeline.dispatch(ManagedFilterPipeline.java:121)
    at com.google.inject.servlet.GuiceFilter.doFilter(GuiceFilter.java:133)
    at com.google.gerrit.httpd.plugins.HttpPluginServlet.service(HttpPluginServlet.java:229)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
    at com.google.inject.servlet.ServletDefinition.doServiceImpl(ServletDefinition.java:290)
    at com.google.inject.servlet.ServletDefinition.doService(ServletDefinition.java:280)
    at com.google.inject.servlet.ServletDefinition.service(ServletDefinition.java:184)
    at com.google.inject.servlet.ManagedServletPipeline.service(ManagedServletPipeline.java:89)
    at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:85)
    at com.google.gerrit.httpd.raw.StaticModule$PolyGerritFilter.doFilter(StaticModule.java:408)
    at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:82)
    at com.google.gerrit.httpd.GetUserFilter.doFilter(GetUserFilter.java:92)
    at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:82)
    at com.google.gerrit.httpd.RequireSslFilter.doFilter(RequireSslFilter.java:72)
    at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:82)
    at com.google.gerrit.httpd.RunAsFilter.doFilter(RunAsFilter.java:120)
    at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:82)
    at com.google.gerrit.httpd.SetThreadNameFilter.doFilter(SetThreadNameFilter.java:62)
    at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:82)
    at com.google.gerrit.httpd.AllRequestFilter$FilterProxy$1.doFilter(AllRequestFilter.java:139)
    at com.google.gerrit.httpd.AllowRenderInFrameFilter.doFilter(AllowRenderInFrameFilter.java:56)
    at com.google.gerrit.httpd.AllRequestFilter$FilterProxy$1.doFilter(AllRequestFilter.java:135)
    at com.google.gerrit.httpd.AllRequestFilter$FilterProxy.doFilter(AllRequestFilter.java:141)
    at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:82)
    at com.google.gerrit.httpd.RequestCleanupFilter.doFilter(RequestCleanupFilter.java:60)
    at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:82)
    at com.google.gerrit.httpd.RequestMetricsFilter.doFilter(RequestMetricsFilter.java:92)
    at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:82)
    at com.google.gerrit.httpd.RequestContextFilter.doFilter(RequestContextFilter.java:64)
    at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:82)
    at com.google.inject.servlet.ManagedFilterPipeline.dispatch(ManagedFilterPipeline.java:121)
    at com.google.inject.servlet.GuiceFilter.doFilter(GuiceFilter.java:133)
    at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193)
    at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1601)
    at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:548)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:233)
    at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1624)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:233)
    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1435)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:188)
    at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:501)
    at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1594)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:186)
    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1350)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
    at org.eclipse.jetty.server.Server.handle(Server.java:516)
    at org.eclipse.jetty.server.HttpChannel.lambda$handle$1(HttpChannel.java:388)
    at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:633)
    at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:380)
    at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:273)
    at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311)
    at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:105)
    at org.eclipse.jetty.io.ChannelEndPoint$1.run(ChannelEndPoint.java:104)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:773)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:905)
    at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.lang.reflect.InvocationTargetException
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
    at org.apache.wicket.session.DefaultPageFactory.createPage(DefaultPageFactory.java:192)
    ... 70 more
Caused by: java.lang.ClassCastException: class com.gitblit.wicket.GitBlitWebSession cannot be cast to class org.apache.wicket.Session (com.gitblit.wicket.GitBlitWebSession is in unnamed module of loader java.net.FactoryURLClassLoader @6901f5fd; org.apache.wicket.Session is in unnamed module of loader java.net.FactoryURLClassLoader @67d3610b)
    at org.apache.wicket.protocol.http.AbstractHttpSessionStore.lookup(AbstractHttpSessionStore.java:245)
    at org.apache.wicket.Session.findOrCreate(Session.java:226)
    at org.apache.wicket.Session.findOrCreate(Session.java:214)
    at org.apache.wicket.Session.get(Session.java:253)
    at org.apache.wicket.Application$1.onInstantiation(Application.java:299)
    at org.apache.wicket.Application.notifyComponentInstantiationListeners(Application.java:1093)
    at org.apache.wicket.Component.<init>(Component.java:926)
orgads commented 1 year ago

I take you build this on Linux? Because I am getting nowhere with macOS.

In order to build, you need to replace external_plugin_deps.bzl in plugins with the one in gitblit. It's in the README.

cd plugins
ln -sf gitblit/external_plugin_deps.bzl .
cd ..
bazel build plugins/gitblit
flaix commented 1 year ago

In order to build, you need to replace external_plugin_deps.bzl in plugins with the one in gitblit. It's in the README.

Yeah, I did that according to the Readme, but I could not get it compiled on macOS. The build didn't like the clang C compiler. So I switched to a Linux VM.

flaix commented 1 year ago

I guess now come the hard problems as we have reached the realms of class loaders.

How can one put some repositories in the container to see that?

orgads commented 1 year ago

Here is a new build for 3.7: gitblit.zip

Rename gitblit.war, use this docker-compose.yml and run docker-compose up:

version: '3'

services:
  gerrit:
    image: gerritcodereview/gerrit:3.7.0
    ports:
      - "8070:8080"
    volumes:
      - ./gitblit.jar:/var/gerrit/plugins/gitblit.jar
      - gerrit-etc:/var/gerrit/etc
      - gerrit-git:/var/gerrit/git
      - gerrit-db:/var/gerrit/db
      - gerrit-index:/var/gerrit/index
      - gerrit-cache:/var/gerrit/cache
    environment:
      - CANONICAL_WEB_URL=http://localhost:8070

volumes:
  gerrit-etc:
  gerrit-git:
  gerrit-db:
  gerrit-index:
  gerrit-cache:

There are 2 repositories that are created automatically, All-Projects and All-Users.

You can reproduce the issue just by opening http://your-server:8080/plugins/gitblit/repositories/

I pushed my latest changes here: https://github.com/orgads/gerrit-gitblit-plugin, on branch master.

Switched back to building gitblit from source, and using MAVEN_LOCAL.

orgads commented 1 year ago

I have to say I'm really confused about https://github.com/orgads/gerrit-gitblit-plugin/commit/d0357a6e15267a687f791149d0d94539fbf56cdb#diff-7065071696a179130d4c9022da41d3b5ca979899627876119e6c88e2573a6a25R140. How come 2 calls to the same function (getAttribute) return different types? The first call for gerrit-username returns Optional<String>, but the second call for gerrit-token returns String. If I change the casts, I get an error (cannot cast Optional to String, or String to Optional). And it's not even consistent. On my system, both return String.

orgads commented 1 year ago

@lucamilanesio @paladox @davido Maybe you'll have ideas regarding https://github.com/gitblit/gitblit/issues/1413#issuecomment-1321131828?

flaix commented 1 year ago

When I run with your docker compose file, I don't get the error about class loaders you pasted. But I do get the class cast exception. This seems something in the plugin, I am guessing. It might depend on where the attributes were set. I don't know if that happens in Gerrit or the plugin. The getAttribute method returns an Object, since any type can be attached to the session as an Object. So type safe handling would probably be to check for the type with an instanceof and act accordingly. But I don't really know about how Gerrit works there.