JacksonMapperConfigurator.java
/*
* Copyright (c) 2022, 2026 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
package org.glassfish.jersey.jackson3.internal;
import jakarta.ws.rs.core.Configuration;
import org.glassfish.jersey.CommonProperties;
import org.glassfish.jersey.jackson3.LocalizationMessages;
import tools.jackson.databind.AnnotationIntrospector;
import tools.jackson.databind.JacksonModule;
import tools.jackson.databind.cfg.MapperBuilder;
import tools.jackson.databind.json.JsonMapper;
import org.glassfish.jersey.jackson3.internal.jackson.jakarta.rs.json.JsonMapperConfigurator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Supplier;
import java.util.logging.Logger;
public class JacksonMapperConfigurator extends JsonMapperConfigurator {
//do not register JaxbAnnotationModule because it breaks default annotations processing
private static final String[] EXCLUDE_MODULE_NAMES = {"JaxbAnnotationModule", "JakartaXmlBindAnnotationModule"};
private static final Logger LOGGER = Logger.getLogger(JacksonMapperConfigurator.class.getName());
private final Configuration commonConfig;
public JacksonMapperConfigurator(JsonMapper mapper, AnnotationIntrospector aiOverride, Configuration commonConfig) {
super(mapper, aiOverride);
this.commonConfig = commonConfig;
}
@Override
protected MapperBuilder<?, ?> _builderWithConfiguration(MapperBuilder<?, ?> mapperBuilder) {
MapperBuilder<?, ?> configuredBuilder = super._builderWithConfiguration(mapperBuilder);
final List<JacksonModule> modules = filterModules(commonConfig, JsonMapper.Builder::findModules);
return configuredBuilder.removeAllModules().addModules(modules);
}
private List<JacksonModule> filterModules(Configuration commonConfig, Supplier<List<JacksonModule>> moduleSupplier) {
final String disabledModules =
CommonProperties.getValue(commonConfig.getProperties(),
commonConfig.getRuntimeType(),
CommonProperties.JSON_JACKSON_DISABLED_MODULES, String.class);
final String enabledModules =
CommonProperties.getValue(commonConfig.getProperties(),
commonConfig.getRuntimeType(),
CommonProperties.JSON_JACKSON_ENABLED_MODULES, String.class);
final List<JacksonModule> modules = new ArrayList<>();
try {
modules.addAll(moduleSupplier.get());
} catch (Throwable e) {
LOGGER.warning(LocalizationMessages.ERROR_MODULES_NOT_LOADED(e.getMessage()));
return modules;
}
for (String exludeModuleName : EXCLUDE_MODULE_NAMES) {
modules.removeIf(mod -> mod.getModuleName().contains(exludeModuleName));
}
if (enabledModules != null && !enabledModules.isEmpty()) {
final List<String> enabledModulesList = Arrays.asList(enabledModules.split(","));
modules.removeIf(mod -> !enabledModulesList.contains(mod.getModuleName()));
} else if (disabledModules != null && !disabledModules.isEmpty()) {
final List<String> disabledModulesList = Arrays.asList(disabledModules.split(","));
modules.removeIf(mod -> disabledModulesList.contains(mod.getModuleName()));
}
return modules;
}
}