Bitbucket proprietary plugin raises an exception (NoClassDefFoundError: javax/net/SocketFactory)

Hello guys,

Quick description of my problem, I hope somebody will be able to help …

  • Bitbucket Plugin developped with Atlassian SDK 8.2.7
  • Bitbucket Server v7.21.17
  • Plugin implements PostRepositoryHook
  • Basically the plugin :
    - logs a RepositoryHookRequest object as a json in a file
    - creates a repository on another bitbucket instance if it does not exist (through a centralized function)
  • No issue encountered when uploading the plugin in Bitbucket GUI
  • When an operation is caught by the hook plugin it logs well the RepositoryHookRequest object but raises an exception when creating the repository to the other Bitbucket server with the stacktrace mentioned bellow
  • this issue is not encountered on a sandbox with the same Bitbucket version : all the execution goes well
  • When running the plugin jar file as a standalone tool on the bitbucket container, it cause no issue ( no NoClassDefFoundError: javax/net/SocketFactory)
    (because the plugin implements another public class that implements a main function)
    example :
bitbucket@bdf8303667c7:~$ java -jar ${BITBUCKET_HOME}/shared/plugins/installed-plugins/plugin_5825296561875632571_hid.bitbucket.plugin.mirror.jar "<another Bitbucket Instance>" "<project name>" "<repository name>" "<repository description>" "<userName>" "<password>"
   [JAR SUCCESS] repo created on mirror : url(<another Bitbucket Instance>), project(<project name>), repo(<repository name>), description(<repository description>)
  • the function BBRepository.createRepoIfNotExists() succeed in “standalone” mode but reports missing class when executed as a hook…

------ stacktrace -------

2023-11-06 14:13:50,341 INFO  [AtlassianEvent::thread-2] jmo @WMI080x853x1730x0 10.16.71.33 "POST /kerberos-scm/iamseng/ac.builder.ext/git-receive-pack HTTP/1.1" c.a.b.plugin.mirror.hook.MirrorHook  ++ pre-mirroring hook/postUpdate ++ COMMIT FOUND : MTObject written in (/var/atlassian/application-data/bitbucket/shared/data/mirroring/commitInfo_c05ec21661a8473aac5612945e65e44ff2f65a62-cad323fb-d339-47f4-9640-60acde3b2957.json)
2023-11-06 14:13:50,694 ERROR [AtlassianEvent::thread-2] jmo @WMI080x853x1730x0 10.16.71.33 "POST /kerberos-scm/iamseng/ac.builder.ext/git-receive-pack HTTP/1.1" c.a.s.i.e.AsyncBatchingInvokersTransformer There was an exception thrown trying to dispatch event 'com.atlassian.stash.internal.event.AnalyticsRepositoryPushEvent[source=com.atlassian.stash.internal.hook.SystemPostRepositoryHook@6c46658e]' for the invoker 'SingleParameterMethodListenerInvoker{method=public void com.atlassian.stash.internal.hook.repository.CoreRefChangeEventToRepositoryHookAdapter.onRefsChanged(com.atlassian.bitbucket.event.repository.RepositoryRefsChangedEvent), listener=com.atlassian.stash.internal.hook.repository.CoreRefChangeEventToRepositoryHookAdapter@48a98bce} (monitored)'
java.lang.RuntimeException: javax/net/SocketFactory. Listener: com.atlassian.stash.internal.hook.repository.CoreRefChangeEventToRepositoryHookAdapter event: com.atlassian.stash.internal.event.AnalyticsRepositoryPushEvent
        at com.atlassian.event.internal.SingleParameterMethodListenerInvoker.invoke(SingleParameterMethodListenerInvoker.java:57)
        at com.atlassian.diagnostics.internal.platform.event.EventSystemMonitor.invokeMonitored(EventSystemMonitor.java:109)
        at com.atlassian.diagnostics.internal.platform.event.MonitoredListenerInvoker.invoke(MonitoredListenerInvoker.java:38)
        at com.atlassian.stash.internal.event.AsyncBatchingInvokersTransformer$AsyncInvokerBatch.invoke(AsyncBatchingInvokersTransformer.java:111)
        at com.atlassian.event.internal.AsynchronousAbleEventDispatcher.lambda$null$0(AsynchronousAbleEventDispatcher.java:37)
        at com.atlassian.sal.core.executor.ThreadLocalDelegateRunnable.run(ThreadLocalDelegateRunnable.java:34)
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
        at com.atlassian.stash.internal.event.EventThreadFactory.lambda$createThread$0(EventThreadFactory.java:35)
        at java.base/java.lang.Thread.run(Thread.java:829)
        ... 1 frame trimmed
Caused by: java.lang.NoClassDefFoundError: javax/net/SocketFactory
        at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createSocket(SSLConnectionSocketFactory.java:315)
        at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:119)
        at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:359)
        at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:381)
        at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:237)
        at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:185)
        at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89)
        at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:111)
        at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185)
        at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)
        at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:56)
        at tools.activbuilder.mt.MTWebClient.execute(MTWebClient.java:310)
        at tools.activbuilder.mt.MTWebClient.restGet(MTWebClient.java:509)
        at tools.activbuilder.vcdriver.bitbucket.VCDriverBitbucket.exists(VCDriverBitbucket.java:234)
        at hid.bitbucket.tools.BBRepository.createRepoIfNotExists(BBRepository.java:41)
        at com.atlassian.bitbucket.plugin.mirror.hook.MirrorHook.postUpdate(MirrorHook.java:105)
        at com.atlassian.stash.internal.hook.repository.DefaultRepositoryHookService.postUpdate(DefaultRepositoryHookService.java:761)
        at com.atlassian.stash.internal.hook.repository.DefaultRepositoryHookService.lambda$doPostUpdate$7(DefaultRepositoryHookService.java:543)
        at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140)
        at com.atlassian.stash.internal.hook.repository.DefaultRepositoryHookService.doPostUpdate(DefaultRepositoryHookService.java:527)
        at com.atlassian.stash.internal.hook.repository.DefaultRepositoryHookService.postUpdate(DefaultRepositoryHookService.java:328)
        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 jdk.internal.reflect.GeneratedMethodAccessor182.invoke(Unknown Source)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at com.atlassian.stash.internal.hook.repository.CoreRefChangeEventToRepositoryHookAdapter.onRefsChanged(CoreRefChangeEventToRepositoryHookAdapter.java:55)
        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 com.atlassian.event.internal.SingleParameterMethodListenerInvoker.invoke(SingleParameterMethodListenerInvoker.java:42)
        ... 9 common frames omitted
Caused by: java.lang.ClassNotFoundException: javax.net.SocketFactory not found by com.atlassian.bitbucket.plugin.mirror.hid.bitbucket.plugin.mirror [139]
        at org.apache.felix.framework.BundleWiringImpl.findClassOrResourceByDelegation(BundleWiringImpl.java:1639)
        ... 40 common frames omitted

Thanks for your help !!

Are you serializing and deserializing the RepositoryHookRequest object ?

Sounds like the remote Bitbucket instance (when it’s not the exact same version) might be having trouble recreating the “RepositoryHookRequest” object based on what you sent over.

Personally I try to avoid serializing/deserializing to complex Java objects and prefer POJOS that only reference String or primitives. Maybe try sending a really simple POJO over the wire instead?

(POJO = plain old java object, aka a “bean” with nothing but getters/setters for primitives or String)

Note: not really 100% confident of my answer here, or even 50% confident.

There is no issue around repositoryHookrequest object serialization (which is hand made) → can be seen in the log with pattern “COMMIT FOUND : MTObject written in ()”.

My issue is around the second step of the process which tries to create a repository on another bitbucket instance… It looks like there is a difference between the 2 runtime environments: the one created by the hook invocation and the one when I call it like with “java -jar …”. → can be seen in the log with “Caused by: java.lang.NoClassDefFoundError: javax/net/SocketFactory”