From 4025a42c42e34bb620f4263de05781a10ddc7a9d Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sat, 11 Jun 2022 14:27:01 -0700 Subject: Inject object mapper --- src/main/java/org/traccar/Context.java | 17 +---------------- src/main/java/org/traccar/MainModule.java | 17 +++++++++++++---- src/main/java/org/traccar/api/AsyncSocket.java | 9 ++++++--- .../java/org/traccar/api/AsyncSocketServlet.java | 13 +++++++++++-- .../java/org/traccar/api/ObjectMapperProvider.java | 4 ++-- .../java/org/traccar/database/DataManager.java | 3 ++- .../java/org/traccar/storage/DatabaseStorage.java | 19 +++++++++++-------- .../java/org/traccar/storage/QueryBuilder.java | 22 +++++++++++++++------- src/main/java/org/traccar/web/WebServer.java | 7 +++++-- 9 files changed, 66 insertions(+), 45 deletions(-) (limited to 'src/main/java') diff --git a/src/main/java/org/traccar/Context.java b/src/main/java/org/traccar/Context.java index 68a711878..54bb2af4b 100644 --- a/src/main/java/org/traccar/Context.java +++ b/src/main/java/org/traccar/Context.java @@ -16,7 +16,6 @@ package org.traccar; import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializationFeature; import org.traccar.config.Config; import org.traccar.config.Keys; import org.traccar.database.BaseObjectManager; @@ -29,7 +28,6 @@ import org.traccar.database.PermissionsManager; import org.traccar.database.UsersManager; import org.traccar.geocoder.Geocoder; import org.traccar.helper.Log; -import org.traccar.helper.SanitizerModule; import org.traccar.model.BaseModel; import org.traccar.model.Device; import org.traccar.model.Group; @@ -55,12 +53,6 @@ public final class Context { return config; } - private static ObjectMapper objectMapper; - - public static ObjectMapper getObjectMapper() { - return objectMapper; - } - private static IdentityManager identityManager; public static IdentityManager getIdentityManager() { @@ -119,7 +111,7 @@ public final class Context { @Override public ObjectMapper getContext(Class clazz) { - return objectMapper; + return Main.getInjector().getInstance(ObjectMapper.class); } } @@ -135,13 +127,6 @@ public final class Context { throw e; } - objectMapper = new ObjectMapper(); - if (config.getBoolean(Keys.WEB_SANITIZE)) { - objectMapper.registerModule(new SanitizerModule()); - } - objectMapper.setConfig( - objectMapper.getSerializationConfig().without(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)); - client = ClientBuilder.newClient().register(new ObjectMapperContextResolver()); if (config.hasKey(Keys.DATABASE_URL)) { diff --git a/src/main/java/org/traccar/MainModule.java b/src/main/java/org/traccar/MainModule.java index a6f983a6b..794735daf 100644 --- a/src/main/java/org/traccar/MainModule.java +++ b/src/main/java/org/traccar/MainModule.java @@ -16,7 +16,9 @@ package org.traccar; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; import com.google.inject.AbstractModule; +import com.google.inject.Injector; import com.google.inject.Provides; import com.google.inject.Scopes; import io.netty.util.HashedWheelTimer; @@ -28,6 +30,7 @@ import org.traccar.broadcast.BroadcastService; import org.traccar.config.Config; import org.traccar.config.Keys; import org.traccar.database.LdapProvider; +import org.traccar.helper.SanitizerModule; import org.traccar.notification.EventForwarder; import org.traccar.session.ConnectionManager; import org.traccar.database.DataManager; @@ -85,8 +88,14 @@ public class MainModule extends AbstractModule { } @Provides - public static ObjectMapper provideObjectMapper() { - return Context.getObjectMapper(); + public static ObjectMapper provideObjectMapper(Config config) { + ObjectMapper objectMapper = new ObjectMapper(); + if (config.getBoolean(Keys.WEB_SANITIZE)) { + objectMapper.registerModule(new SanitizerModule()); + } + objectMapper.setConfig(objectMapper + .getSerializationConfig().without(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)); + return objectMapper; } @Provides @@ -145,9 +154,9 @@ public class MainModule extends AbstractModule { } @Provides - public static WebServer provideWebServer(Config config) { + public static WebServer provideWebServer(Injector injector, Config config) { if (config.hasKey(Keys.WEB_PORT)) { - return new WebServer(config); + return new WebServer(injector, config); } return null; } diff --git a/src/main/java/org/traccar/api/AsyncSocket.java b/src/main/java/org/traccar/api/AsyncSocket.java index b5902c4fb..2b866176b 100644 --- a/src/main/java/org/traccar/api/AsyncSocket.java +++ b/src/main/java/org/traccar/api/AsyncSocket.java @@ -1,5 +1,5 @@ /* - * Copyright 2015 - 2021 Anton Tananaev (anton@traccar.org) + * Copyright 2015 - 2022 Anton Tananaev (anton@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,7 @@ package org.traccar.api; import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; import org.eclipse.jetty.websocket.api.Session; import org.eclipse.jetty.websocket.api.WebSocketAdapter; import org.slf4j.Logger; @@ -39,9 +40,11 @@ public class AsyncSocket extends WebSocketAdapter implements ConnectionManager.U private static final String KEY_POSITIONS = "positions"; private static final String KEY_EVENTS = "events"; + private final ObjectMapper objectMapper; private final long userId; - public AsyncSocket(long userId) { + public AsyncSocket(ObjectMapper objectMapper, long userId) { + this.objectMapper = objectMapper; this.userId = userId; } @@ -92,7 +95,7 @@ public class AsyncSocket extends WebSocketAdapter implements ConnectionManager.U private void sendData(Map> data) { if (isConnected()) { try { - getRemote().sendString(Context.getObjectMapper().writeValueAsString(data), null); + getRemote().sendString(objectMapper.writeValueAsString(data), null); } catch (JsonProcessingException e) { LOGGER.warn("Socket JSON formatting error", e); } diff --git a/src/main/java/org/traccar/api/AsyncSocketServlet.java b/src/main/java/org/traccar/api/AsyncSocketServlet.java index a964ead10..4e55dfebf 100644 --- a/src/main/java/org/traccar/api/AsyncSocketServlet.java +++ b/src/main/java/org/traccar/api/AsyncSocketServlet.java @@ -1,5 +1,5 @@ /* - * Copyright 2015 - 2021 Anton Tananaev (anton@traccar.org) + * Copyright 2015 - 2022 Anton Tananaev (anton@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,24 +15,33 @@ */ package org.traccar.api; +import com.fasterxml.jackson.databind.ObjectMapper; import org.eclipse.jetty.websocket.server.JettyWebSocketServlet; import org.eclipse.jetty.websocket.server.JettyWebSocketServletFactory; import org.traccar.Context; import org.traccar.api.resource.SessionResource; import org.traccar.config.Keys; +import javax.inject.Inject; import javax.servlet.http.HttpSession; import java.time.Duration; public class AsyncSocketServlet extends JettyWebSocketServlet { + private final ObjectMapper objectMapper; + + @Inject + public AsyncSocketServlet(ObjectMapper objectMapper) { + this.objectMapper = objectMapper; + } + @Override public void configure(JettyWebSocketServletFactory factory) { factory.setIdleTimeout(Duration.ofMillis(Context.getConfig().getLong(Keys.WEB_TIMEOUT))); factory.setCreator((req, resp) -> { if (req.getSession() != null) { long userId = (Long) ((HttpSession) req.getSession()).getAttribute(SessionResource.USER_ID_KEY); - return new AsyncSocket(userId); + return new AsyncSocket(objectMapper, userId); } else { return null; } diff --git a/src/main/java/org/traccar/api/ObjectMapperProvider.java b/src/main/java/org/traccar/api/ObjectMapperProvider.java index f81b20917..cb7adab6c 100644 --- a/src/main/java/org/traccar/api/ObjectMapperProvider.java +++ b/src/main/java/org/traccar/api/ObjectMapperProvider.java @@ -16,7 +16,7 @@ package org.traccar.api; import com.fasterxml.jackson.databind.ObjectMapper; -import org.traccar.Context; +import org.traccar.Main; import javax.ws.rs.ext.ContextResolver; import javax.ws.rs.ext.Provider; @@ -26,7 +26,7 @@ public class ObjectMapperProvider implements ContextResolver { @Override public ObjectMapper getContext(Class type) { - return Context.getObjectMapper(); + return Main.getInjector().getInstance(ObjectMapper.class); } } diff --git a/src/main/java/org/traccar/database/DataManager.java b/src/main/java/org/traccar/database/DataManager.java index 29d70ec32..556f1e348 100644 --- a/src/main/java/org/traccar/database/DataManager.java +++ b/src/main/java/org/traccar/database/DataManager.java @@ -15,6 +15,7 @@ */ package org.traccar.database; +import com.fasterxml.jackson.databind.ObjectMapper; import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; import liquibase.Contexts; @@ -78,7 +79,7 @@ public class DataManager { initDatabase(); initDatabaseSchema(); - storage = new DatabaseStorage(dataSource); + storage = new DatabaseStorage(dataSource, Main.getInjector().getInstance(ObjectMapper.class)); } private void initDatabase() throws Exception { diff --git a/src/main/java/org/traccar/storage/DatabaseStorage.java b/src/main/java/org/traccar/storage/DatabaseStorage.java index fc468182e..661e792d4 100644 --- a/src/main/java/org/traccar/storage/DatabaseStorage.java +++ b/src/main/java/org/traccar/storage/DatabaseStorage.java @@ -15,6 +15,7 @@ */ package org.traccar.storage; +import com.fasterxml.jackson.databind.ObjectMapper; import org.traccar.model.BaseModel; import org.traccar.model.Device; import org.traccar.model.Group; @@ -38,9 +39,11 @@ import java.util.stream.Collectors; public class DatabaseStorage extends Storage { private final DataSource dataSource; + private final ObjectMapper objectMapper; - public DatabaseStorage(DataSource dataSource) { + public DatabaseStorage(DataSource dataSource, ObjectMapper objectMapper) { this.dataSource = dataSource; + this.objectMapper = objectMapper; } @Override @@ -52,7 +55,7 @@ public class DatabaseStorage extends Storage { query.append(formatOrder(request.getOrder())); query.append(formatLimit(request.getLimit())); try { - QueryBuilder builder = QueryBuilder.create(dataSource, query.toString()); + QueryBuilder builder = QueryBuilder.create(dataSource, objectMapper, query.toString()); for (Map.Entry variable : getConditionVariables(request.getCondition()).entrySet()) { builder.setValue(variable.getKey(), variable.getValue()); } @@ -72,7 +75,7 @@ public class DatabaseStorage extends Storage { query.append(formatColumns(request.getColumns(), entity.getClass(), "set", c -> ':' + c)); query.append(")"); try { - QueryBuilder builder = QueryBuilder.create(dataSource, query.toString(), true); + QueryBuilder builder = QueryBuilder.create(dataSource, objectMapper, query.toString(), true); builder.setObject(entity); return builder.executeUpdate(); } catch (SQLException e) { @@ -88,7 +91,7 @@ public class DatabaseStorage extends Storage { query.append(formatColumns(request.getColumns(), entity.getClass(), "set", c -> c + " = :" + c)); query.append(formatCondition(request.getCondition())); try { - QueryBuilder builder = QueryBuilder.create(dataSource, query.toString()); + QueryBuilder builder = QueryBuilder.create(dataSource, objectMapper, query.toString()); builder.setObject(entity); for (Map.Entry variable : getConditionVariables(request.getCondition()).entrySet()) { builder.setValue(variable.getKey(), variable.getValue()); @@ -105,7 +108,7 @@ public class DatabaseStorage extends Storage { query.append(getStorageName(clazz)); query.append(formatCondition(request.getCondition())); try { - QueryBuilder builder = QueryBuilder.create(dataSource, query.toString()); + QueryBuilder builder = QueryBuilder.create(dataSource, objectMapper, query.toString()); for (Map.Entry variable : getConditionVariables(request.getCondition()).entrySet()) { builder.setValue(variable.getKey(), variable.getValue()); } @@ -133,7 +136,7 @@ public class DatabaseStorage extends Storage { Condition combinedCondition = Condition.merge(conditions); query.append(formatCondition(combinedCondition)); try { - QueryBuilder builder = QueryBuilder.create(dataSource, query.toString()); + QueryBuilder builder = QueryBuilder.create(dataSource, objectMapper, query.toString()); for (Map.Entry variable : getConditionVariables(combinedCondition).entrySet()) { builder.setValue(variable.getKey(), variable.getValue()); } @@ -151,7 +154,7 @@ public class DatabaseStorage extends Storage { query.append(permission.get().keySet().stream().map(key -> ':' + key).collect(Collectors.joining(", "))); query.append(")"); try { - QueryBuilder builder = QueryBuilder.create(dataSource, query.toString(), true); + QueryBuilder builder = QueryBuilder.create(dataSource, objectMapper, query.toString(), true); for (var entry : permission.get().entrySet()) { builder.setLong(entry.getKey(), entry.getValue()); } @@ -169,7 +172,7 @@ public class DatabaseStorage extends Storage { query.append(permission .get().keySet().stream().map(key -> key + " = :" + key).collect(Collectors.joining(" AND "))); try { - QueryBuilder builder = QueryBuilder.create(dataSource, query.toString(), true); + QueryBuilder builder = QueryBuilder.create(dataSource, objectMapper, query.toString(), true); for (var entry : permission.get().entrySet()) { builder.setLong(entry.getKey(), entry.getValue()); } diff --git a/src/main/java/org/traccar/storage/QueryBuilder.java b/src/main/java/org/traccar/storage/QueryBuilder.java index 874a046b4..8502d5f0b 100644 --- a/src/main/java/org/traccar/storage/QueryBuilder.java +++ b/src/main/java/org/traccar/storage/QueryBuilder.java @@ -16,6 +16,7 @@ package org.traccar.storage; import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.traccar.Context; @@ -45,13 +46,18 @@ public final class QueryBuilder { private static final Logger LOGGER = LoggerFactory.getLogger(QueryBuilder.class); + private final ObjectMapper objectMapper; + private final Map> indexMap = new HashMap<>(); private Connection connection; private PreparedStatement statement; private final String query; private final boolean returnGeneratedKeys; - private QueryBuilder(DataSource dataSource, String query, boolean returnGeneratedKeys) throws SQLException { + private QueryBuilder( + DataSource dataSource, ObjectMapper objectMapper, + String query, boolean returnGeneratedKeys) throws SQLException { + this.objectMapper = objectMapper; this.query = query; this.returnGeneratedKeys = returnGeneratedKeys; if (query != null) { @@ -126,13 +132,15 @@ public final class QueryBuilder { return parsedQuery.toString(); } - public static QueryBuilder create(DataSource dataSource, String query) throws SQLException { - return new QueryBuilder(dataSource, query, false); + public static QueryBuilder create( + DataSource dataSource, ObjectMapper objectMapper, String query) throws SQLException { + return new QueryBuilder(dataSource, objectMapper, query, false); } public static QueryBuilder create( - DataSource dataSource, String query, boolean returnGeneratedKeys) throws SQLException { - return new QueryBuilder(dataSource, query, returnGeneratedKeys); + DataSource dataSource, ObjectMapper objectMapper, String query, + boolean returnGeneratedKeys) throws SQLException { + return new QueryBuilder(dataSource, objectMapper, query, returnGeneratedKeys); } private List indexes(String name) { @@ -295,7 +303,7 @@ public final class QueryBuilder { } else if (method.getReturnType().equals(byte[].class)) { setBlob(name, (byte[]) method.invoke(object)); } else { - setString(name, Context.getObjectMapper().writeValueAsString(method.invoke(object))); + setString(name, objectMapper.writeValueAsString(method.invoke(object))); } } catch (IllegalAccessException | InvocationTargetException | JsonProcessingException error) { LOGGER.warn("Get property error", error); @@ -378,7 +386,7 @@ public final class QueryBuilder { String value = resultSet.getString(name); if (value != null && !value.isEmpty()) { try { - method.invoke(object, Context.getObjectMapper().readValue(value, parameterType)); + method.invoke(object, objectMapper.readValue(value, parameterType)); } catch (InvocationTargetException | IllegalAccessException | IOException error) { LOGGER.warn("Set property error", error); } diff --git a/src/main/java/org/traccar/web/WebServer.java b/src/main/java/org/traccar/web/WebServer.java index fdbfc1464..933e8c845 100644 --- a/src/main/java/org/traccar/web/WebServer.java +++ b/src/main/java/org/traccar/web/WebServer.java @@ -15,6 +15,7 @@ */ package org.traccar.web; +import com.google.inject.Injector; import com.google.inject.servlet.GuiceFilter; import org.eclipse.jetty.http.HttpCookie; import org.eclipse.jetty.http.HttpMethod; @@ -78,10 +79,12 @@ public class WebServer implements LifecycleObject { private static final Logger LOGGER = LoggerFactory.getLogger(WebServer.class); + private final Injector injector; private final Server server; @Inject - public WebServer(Config config) { + public WebServer(Injector injector, Config config) { + this.injector = injector; String address = config.getString(Keys.WEB_ADDRESS); int port = config.getInteger(Keys.WEB_PORT); if (address == null) { @@ -169,7 +172,7 @@ public class WebServer implements LifecycleObject { private void initApi(Config config, ServletContextHandler servletHandler) { servletHandler.addFilter(GuiceFilter.class, "/api/*", EnumSet.allOf(DispatcherType.class)); - servletHandler.addServlet(new ServletHolder(new AsyncSocketServlet()), "/api/socket"); + servletHandler.addServlet(new ServletHolder(injector.getInstance(AsyncSocketServlet.class)), "/api/socket"); JettyWebSocketServletContainerInitializer.configure(servletHandler, null); String mediaPath = config.getString(Keys.MEDIA_PATH); -- cgit v1.2.3