Hacktoberfest 2026:维护者为十月标记出来的 issue,仍然开放、适合新手。 浏览 Hacktoberfest issue

google-http-client-jackson2 cannot be excluded even when a JsonFactory is configured via FirebaseOptions

未关闭
#1,231 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

评估

难度
4/5
预计耗时
3-5 天
新手友好度
48/100
Issue 类型
缺陷
描述清晰度
基本清楚
活跃度
冷清
技术栈
java
领域
api, backend

调研方向

从 ApiClientUtils.java 和堆栈跟踪中显示的 FirebaseMessagingClientImpl.fromApp 路径开始,然后使用 issue 中的 FirebaseOptions 配置重现 Maven 排除和首次发送失败。确定配置的 JsonFactory 是否在 request-factory 或 credentials 初始化期间被绕过。完成的标准是:对于此配置不再需要 Jackson2,或者已记录该硬性要求。

由索引模型根据 Issue 内容生成。

描述

Describe your environment
  • Operating System version: Amazon Linux 2023 (AWS ECS Fargate), also reproduced on macOS 15
  • Firebase SDK version: 9.7.1 (the code in question is unchanged on v9.10.0)
  • Library version: com.google.firebase:firebase-admin:9.7.1, Java 25, Spring Boot 4.1
  • Firebase Product: messaging (FCM only — no Firestore, Storage, Realtime Database or FirebaseAuth)
Describe the problem

google-http-client-jackson2 is a hard runtime requirement, and FirebaseOptions.setJsonFactory(...) is not sufficient to avoid it. Excluding the artifact still throws ClassNotFoundException on the first FCM send, which forces ~580 KB of Jackson 2 into deployments whose Firebase usage is otherwise entirely Gson-based.

Steps to reproduce:
  1. Configure FirebaseOptions with an explicit transport and JSON factory (see code below).
  2. Exclude com.google.http-client:google-http-client-jackson2 from the build.
  3. Start the application — startup succeeds, both FirebaseApp instances initialize fine.
  4. Send a message via FirebaseMessaging.sendEachForMulticast(...) — fails:
java.lang.ClassNotFoundException: com.google.api.client.json.jackson2.JacksonFactory
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:580)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:490)
    at com.google.firebase.messaging.FirebaseMessagingClientImpl.fromApp(FirebaseMessagingClientImpl.java:193)
    at com.google.firebase.messaging.FirebaseMessaging$7.get(FirebaseMessaging.java:637)
    at com.google.firebase.messaging.FirebaseMessaging$7.get(FirebaseMessaging.java:634)
    at com.google.common.base.Suppliers$NonSerializableMemoizingSupplier.get(Suppliers.java:201)
    at com.google.firebase.messaging.FirebaseMessaging.getMessagingClient(FirebaseMessaging.java:519)
    at com.google.firebase.messaging.FirebaseMessaging.sendOpForSendResponse(FirebaseMessaging.java:253)

The failure only surfaces on the first send, because getMessagingClient() is lazy and memoized — so a startup smoke test does not catch it.

The configured factory does appear to be honoured for messaging itself; something in the request-factory / credentials initialization path loads JacksonFactory regardless of configuration.

Relevant Code:
FirebaseOptions.builder()
    .setHttpTransport(new NetHttpTransport())
    .setJsonFactory(GsonFactory.getDefaultInstance())
    .setCredentials(GoogleCredentials.fromStream(serviceAccountJson))
    .build();

We use FCM only, and prune the parts of the SDK we do not need:

<dependency>
    <groupId>com.google.firebase</groupId>
    <artifactId>firebase-admin</artifactId>
    <exclusions>
        <exclusion>
            <groupId>com.google.cloud</groupId>
            <artifactId>*</artifactId>
        </exclusion>
        <exclusion>
            <groupId>io.netty</groupId>
            <artifactId>*</artifactId>
        </exclusion>
    </exclusions>
</dependency>
Why this matters

After that pruning, everything remaining is Gson-based. Credentials come from GoogleCredentials, and google-auth-library-oauth2-http uses GsonFactory (OAuth2Utils.JSON_FACTORY), which brings google-http-client-gson + gson 2.13.2 (283 KB) in at compile scope. Despite that, we must also ship:

+- com.google.http-client:google-http-client-jackson2:jar:runtime
|  \- com.fasterxml.jackson.core:jackson-core:jar:2.21.4:runtime   <- 580 KB, sole consumer

Jackson 2 is roughly twice the size of the Gson stack it duplicates, and nothing else on our classpath requires it.

This is amplified on Spring Boot 4.x, which moved to Jackson 3 (tools.jackson). Applications now carry both Jackson generations side by side, with Jackson 2 present solely to satisfy firebase-admin.

The blocker cited in the code may be stale
public static JsonFactory getDefaultJsonFactory() {
    // Force using the Jackson2 parser for this project for now. Eventually we should switch
    // to Gson, but there are some issues that are preventing this migration at the moment.
    // See https://github.com/googleapis/google-api-java-client/issues/1779 for details.
    return JacksonFactory.getDefaultInstance();
}

googleapis/google-api-java-client#1779 was closed on 2021-04-29 as triage rather than fixed, splitting into three sub-bugs. Per a 2023-03-03 comment on that issue from a Gson maintainer:

  • floating-point serialization — fixed
  • parser leniency — addressed by Gson's strict-parsing API
  • exception handling — tracked in googleapis/google-http-java-client#1353, which is a documentation issue

ApiClientUtils.java does not appear to have been revisited on this point since (subsequent commits touch transports and copyright headers).

Ask

Any of these would help:

  1. Make the Jackson2 dependency genuinely optional when a JsonFactory is supplied via FirebaseOptions.
  2. Switch the default to GsonFactory, if the 2021 blockers no longer apply.
  3. Failing both, document that google-http-client-jackson2 is a hard requirement — that alone would save others the investigation.
主要语言
Java
星标
620
派生
305
平均合并
4 天 9 小时
30 天内合并 PR
4

贡献指南

打开贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

firebase/firebase-admin-java 的其他 Issue

查看 firebase/firebase-admin-java 的全部 Issue

相似的 Issue

更多 Java Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。