Java tutorial
/** * Mule Morphia Connector * * Copyright (c) MuleSoft, Inc. All rights reserved. http://www.mulesoft.com * * The software in this package is published under the terms of the CPAL v1.0 * license, a copy of which has been included with this distribution in the * LICENSE.txt file. */ package org.mule.modules.morphia; import com.github.jmkgreen.morphia.Datastore; import com.github.jmkgreen.morphia.Key; import com.github.jmkgreen.morphia.Morphia; import com.github.jmkgreen.morphia.logging.MorphiaLoggerFactory; import com.github.jmkgreen.morphia.mapping.Mapper; import com.github.jmkgreen.morphia.mapping.MappingException; import com.github.jmkgreen.morphia.mapping.cache.EntityCache; import com.github.jmkgreen.morphia.query.Query; import com.github.jmkgreen.morphia.query.UpdateOperations; import com.github.jmkgreen.morphia.query.UpdateResults; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.mongodb.BasicDBList; import com.mongodb.BasicDBObjectBuilder; import com.mongodb.CommandResult; import com.mongodb.DBObject; import com.mongodb.DBRef; import com.mongodb.Mongo; import com.mongodb.MongoException; import com.mongodb.MongoOptions; import com.mongodb.ServerAddress; import com.mongodb.WriteResult; import com.mongodb.util.JSON; import org.bson.types.ObjectId; import org.codehaus.jackson.JsonFactory; import org.codehaus.jackson.JsonGenerator; import org.mule.api.annotations.Configurable; import org.mule.api.annotations.Mime; import org.mule.api.annotations.Module; import org.mule.api.annotations.Processor; import org.mule.api.annotations.display.Password; import org.mule.api.annotations.param.Default; import org.mule.api.annotations.param.Optional; import org.mule.transformer.types.MimeTypes; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.StringTokenizer; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ExecutionException; /** * Morphia is a lightweight type-safe library for mapping Java objects to/from MongoDB: * <p/> * <ul> * <li>Easy to use, and very lightweight; reflection is used once per type and cached for good performance.</li> * <li>Datastore and DAO<T,V> access abstractions, or roll your own...</li> * <li>Type-safe, and Fluent Query support with (runtime) validation</li> * <li>Annotations based mapping behavior; there are no XML files.</li> * <li>Extensions: Validation (jsr303), and SLF4J Logging</li> * </ul> * * @author MuleSoft, Inc. */ @Module(name = "morphia", schemaVersion = "1.0") public class MorphiaConnector { /** * List of class names with mappings */ @Configurable @Optional private List<String> classes; /** * List of packages with mappings */ @Configurable @Optional private List<String> packages; /** * Specifies whether to ignore classes in the package that cannot be mapped */ @Configurable @Optional @Default("true") private boolean ignoreInvalidClasses; /** * Ensure indexes on the background */ @Configurable @Optional @Default("true") private boolean ensureIndexesOnBackground; /** * The number of connections allowed per host (the pool size, per host) */ @Configurable @Optional public Integer connectionsPerHost; /** * Multiplier for connectionsPerHost for # of threads that can block */ @Configurable @Optional public Integer threadsAllowedToBlockForConnectionMultiplier; /** * The max wait time for a blocking thread for a connection from the pool in ms. */ @Configurable @Optional public Integer maxWaitTime; /** * The connection timeout in milliseconds; this is for establishing the socket connections (open). 0 is default and infinite. */ @Configurable @Optional private Integer connectTimeout; /** * The socket timeout. 0 is default and infinite. */ @Configurable @Optional private Integer socketTimeout; /** * This controls whether the system retries automatically on connection errors. */ @Configurable @Optional private Boolean autoConnectRetry; /** * Specifies if the driver is allowed to read from secondaries or slaves. */ @Configurable @Optional private Boolean slaveOk; /** * If the driver sends a getLastError command after every update to ensure it succeeded. */ @Configurable @Optional public Boolean safe; /** * If set, the w value of WriteConcern for the connection is set to this. */ @Configurable @Optional public Integer w; /** * If set, the wtimeout value of WriteConcern for the connection is set to this. */ @Configurable @Optional public Integer wtimeout; /** * Sets the fsync value of WriteConcern for the connection. */ @Configurable @Optional public Boolean fsync; /** * The username to use in case authentication is required */ @Configurable @Optional private String username; /** * The password to use in case authentication is required, null if no authentication is desired */ @Configurable @Optional @Password private String password; /** * The host of the Mongo server. If the host is part of a replica set then you can specify all the * hosts separated by comma. */ @Configurable @Optional @Default("localhost") private String host; /** * The port of the Mongo server */ @Configurable @Optional @Default("27017") private int port; /** * Default database */ @Configurable @Optional private String database; /** * Datastore Cache */ private LoadingCache<MorphiaCacheKey, Datastore> datastoreCache; /** * Mongo Instances Cache */ private LoadingCache<MongoCacheKey, Mongo> mongoCache; static { MorphiaLoggerFactory.registerLogger(SFL4JLogrFactory.class); } /** * Construct a new instance of Morphia */ @PostConstruct public void init() throws ClassNotFoundException { this.mongoCache = CacheBuilder.newBuilder().maximumSize(10).build(new CacheLoader<MongoCacheKey, Mongo>() { public Mongo load(MongoCacheKey cacheKey) { return new Mongo(cacheKey.getSeeds(), cacheKey.getOptions()); } }); this.datastoreCache = CacheBuilder.newBuilder().maximumSize(50) .build(new CacheLoader<MorphiaCacheKey, Datastore>() { private Morphia morphia; @Override public Datastore load(MorphiaCacheKey morphiaCacheKey) throws Exception { initMorphia(); List<ServerAddress> seeds = getSeeds(morphiaCacheKey.getHost(), morphiaCacheKey.getPort()); MongoCacheKey mongoCacheKey = new MongoCacheKey(seeds, getMongoOptions()); Mongo mongo = mongoCache.get(mongoCacheKey); Datastore datastore = this.morphia.createDatastore(mongo, morphiaCacheKey.getDatabase(), morphiaCacheKey.getUsername(), morphiaCacheKey.getPassword().toCharArray()); datastore.ensureIndexes(ensureIndexesOnBackground); datastore.ensureCaps(); return datastore; } private void initMorphia() throws ClassNotFoundException { if (morphia == null) { morphia = new Morphia(); if (classes != null) { for (String className : classes) { this.morphia.map(Class.forName(className)); } } if (packages != null) { for (String packageName : packages) { this.morphia.mapPackage(packageName, ignoreInvalidClasses); } } } } private List<ServerAddress> getSeeds(String host, int port) throws UnknownHostException { List<ServerAddress> seeds = new ArrayList<ServerAddress>(); if (host.indexOf(',') != -1) { StringTokenizer tokenizer = new StringTokenizer(host, ","); while (tokenizer.hasMoreTokens()) { seeds.add(new ServerAddress(tokenizer.nextToken(), port)); } } else { seeds.add(new ServerAddress(host, port)); } return seeds; } private MongoOptions getMongoOptions() { MongoOptions options = new MongoOptions(); if (connectionsPerHost != null) options.connectionsPerHost = connectionsPerHost; if (threadsAllowedToBlockForConnectionMultiplier != null) options.threadsAllowedToBlockForConnectionMultiplier = threadsAllowedToBlockForConnectionMultiplier; if (maxWaitTime != null) options.maxWaitTime = maxWaitTime; if (connectTimeout != null) options.connectTimeout = connectTimeout; if (socketTimeout != null) options.socketTimeout = socketTimeout; if (autoConnectRetry != null) options.autoConnectRetry = autoConnectRetry; if (slaveOk != null) options.slaveOk = slaveOk; if (safe != null) options.safe = safe; if (w != null) options.w = w; if (wtimeout != null) options.wtimeout = wtimeout; if (fsync != null) options.fsync = fsync; return options; } }); } @PreDestroy public void shutdown() { ConcurrentMap<MongoCacheKey, Mongo> map = this.mongoCache.asMap(); for (MongoCacheKey key : map.keySet()) { map.get(key).close(); } } /** * Method invoked when a new datastore needs to be accessed * * @param username the username to use in case authentication is required * @param password the password to use in case authentication is required, null * if no authentication is desired * @param host The host of the Mongo server. If the host is part of a replica set then you can specify all the hosts * separated by comma. * @param port The port of the Mongo server * @param database The database name of the Mongo server * @throws ExecutionException if there is a connection exception */ public Datastore getDatastore(String username, String password, String database, String host, Integer port) throws ExecutionException { String trueUsername = null; String truePassword = null; String trueDatabase = null; String trueHost = null; Integer truePort = null; if (username == null) { trueUsername = this.username; } else { trueUsername = username; } if (database == null) { trueDatabase = this.database; } else { trueDatabase = database; } if (password == null) { truePassword = this.password; } else { truePassword = password; } if (host == null) { trueHost = this.host; } else { trueHost = host; } if (port == null) { truePort = this.port; } else { truePort = port; } MorphiaCacheKey morphiaCacheKey = new MorphiaCacheKey(trueDatabase, trueUsername, truePassword, trueHost, truePort); return this.datastoreCache.get(morphiaCacheKey); } /** * Add a new user to the database * <p/> * {@sample.xml ../../../doc/mule-module-morphia.xml.sample morphia:add-user} * * @param newUsername Username to be created * @param newPassword Password that will be used for authentication * @param targetDatabase Database at which this user will be created. It defaults to the current one if not specified. * @param username the username to use in case authentication is required * @param password the password to use in case authentication is required, null * if no authentication is desired * @param host The host of the Mongo server. If the host is part of a replica set then you can specify all the hosts * separated by comma. * @param port The port of the Mongo server * @param database The database name of the Mongo server * @throws ExecutionException if there is a connection exception */ @Processor public void addUser(String newUsername, String newPassword, @Optional String targetDatabase, @Optional String username, @Optional @Password String password, @Optional String host, @Optional Integer port, @Optional String database) throws ExecutionException { Datastore datastore = getDatastore(username, password, database, host, port); WriteResult writeResult = null; if (targetDatabase == null) { writeResult = datastore.getDB().addUser(newUsername, newPassword.toCharArray()); } else { writeResult = datastore.getDB().getMongo().getDB(targetDatabase).addUser(newUsername, newPassword.toCharArray()); } if (!writeResult.getLastError().ok()) { throw new MongoException(writeResult.getLastError().getErrorMessage()); } } /** * Drop the current database * <p/> * {@sample.xml ../../../doc/mule-module-morphia.xml.sample morphia:drop-database} * * @param username the username to use in case authentication is required * @param password the password to use in case authentication is required, null * if no authentication is desired * @param host The host of the Mongo server. If the host is part of a replica set then you can specify all the hosts * separated by comma. * @param port The port of the Mongo server * @param database The database name of the Mongo server * @throws ExecutionException if there is a connection exception */ @Processor public void dropDatabase(@Optional String username, @Optional @Password String password, @Optional String host, @Optional Integer port, @Optional String database) throws ExecutionException { Datastore datastore = getDatastore(username, password, database, host, port); datastore.getDB().dropDatabase(); } /** * Saves the entity (Object) and updates the @Id field * <p/> * {@sample.xml ../../../doc/mule-module-morphia.xml.sample morphia:save} * {@sample.xml ../../../doc/mule-module-morphia.xml.sample morphia:save-with-ref} * * @param object Object to be saved * @param writeConcern Sets the write concern for this database. It Will be used for writes to any collection in * this database. See the documentation for {@link WriteConcern} for more information. * @param username the username to use in case authentication is required * @param password the password to use in case authentication is required, null * if no authentication is desired * @param host The host of the Mongo server. If the host is part of a replica set then you can specify all the hosts * separated by comma. * @param port The port of the Mongo server * @param database The database name of the Mongo server * @throws ExecutionException if there is a connection exception * @return An instance of {@link com.github.jmkgreen.morphia.Key} */ @Processor public Object save(@Optional @Default("#[payload]") Object object, @Optional @Default("ACKNOWLEDGED") WriteConcern writeConcern, @Optional String username, @Optional @Password String password, @Optional String host, @Optional Integer port, @Optional String database) throws ExecutionException { Datastore datastore = getDatastore(username, password, database, host, port); return datastore.save(object, writeConcern.getMongoWriteConcern()); } /** * Saves the iterable collection and updates the @Id field * <p/> * {@sample.xml ../../../doc/mule-module-morphia.xml.sample morphia:save-multiple} * * @param collection The iterable collection to be saved * @param writeConcern Sets the write concern for this database. It Will be used for writes to any collection in * this database. See the documentation for {@link WriteConcern} for more information. * @param username the username to use in case authentication is required * @param password the password to use in case authentication is required, null * if no authentication is desired * @param host The host of the Mongo server. If the host is part of a replica set then you can specify all the hosts * separated by comma. * @param port The port of the Mongo server * @param database The database name of the Mongo server * @throws ExecutionException if there is a connection exception * @return An iterable collection of {@link com.github.jmkgreen.morphia.Key} */ @Processor public Iterable<Object> saveMultiple(@Optional @Default("#[payload]") Iterable collection, @Optional @Default("ACKNOWLEDGED") WriteConcern writeConcern, @Optional String username, @Optional @Password String password, @Optional String host, @Optional Integer port, @Optional String database) throws ExecutionException { Datastore datastore = getDatastore(username, password, database, host, port); return datastore.save(collection, writeConcern.getMongoWriteConcern()); } /** * Does the object exists? * <p/> * {@sample.xml ../../../doc/mule-module-morphia.xml.sample morphia:exists} * * @param filters Filter criteria. Criteria is a composite of the field name and the operator ("field >", or "field in"). All criteria are implicitly combined with a logical "and". * @param className Class name of the object to retrieve * @param username the username to use in case authentication is required * @param exception The exception that needs to be thrown if the object does not exist. It must be a RuntimeException. * @param disableCursorTimeout Disables cursor timeout on server * @param disableSnapshotMode Disable snapshotted mode (default mode). This will be faster but changes made * during the cursor may cause duplicates. * @param disableValidation Turns off validation * @param password the password to use in case authentication is required, null * if no authentication is desired * @param host The host of the Mongo server. If the host is part of a replica set then you can specify all the hosts * separated by comma. * @param port The port of the Mongo server * @param database The database name of the Mongo server * @return True if it exists, false otherwise * @throws ExecutionException if there is a connection exception * @throws ClassNotFoundException If the class cannot be found */ @Processor public boolean exists(String className, Map<String, Object> filters, @Optional String exception, @Optional Boolean disableCursorTimeout, @Optional Boolean disableSnapshotMode, @Optional Boolean disableValidation, @Optional String username, @Optional @Password String password, @Optional String host, @Optional Integer port, @Optional String database) throws ClassNotFoundException, ExecutionException { Datastore datastore = getDatastore(username, password, database, host, port); QueryBuilder queryBuilder = QueryBuilder.newBuilder(datastore, className).setFilters(filters) .setDisableValidation(disableValidation).setDisableCursorTimeout(disableCursorTimeout) .setDisableSnapshotMode(disableSnapshotMode); boolean exists = datastore.getCount(queryBuilder.getQuery()) > 0; if (!exists && exception != null) { throw getExceptionFromClassName(exception); } return exists; } /** * Validates that the object does not exist and throws an exception if it does * <p/> * {@sample.xml ../../../doc/mule-module-morphia.xml.sample morphia:exists} * * @param filters Filter criteria. Criteria is a composite of the field name and the operator ("field >", or "field in"). All criteria are implicitly combined with a logical "and". * @param className Class name of the object to retrieve * @param username the username to use in case authentication is required * @param exception The exception that needs to be thrown if the object exists. It must be a RuntimeException. * @param disableCursorTimeout Disables cursor timeout on server * @param disableSnapshotMode Disable snapshotted mode (default mode). This will be faster but changes made * during the cursor may cause duplicates. * @param disableValidation Turns off validation * @param password the password to use in case authentication is required, null * if no authentication is desired * @param host The host of the Mongo server. If the host is part of a replica set then you can specify all the hosts * separated by comma. * @param port The port of the Mongo server * @param database The database name of the Mongo server * @return True if it doesn't exists, false otherwise * @throws ExecutionException if there is a connection exception * @throws ClassNotFoundException If the class cannot be found */ @Processor public void notExists(String className, Map<String, Object> filters, String exception, @Optional Boolean disableCursorTimeout, @Optional Boolean disableSnapshotMode, @Optional Boolean disableValidation, @Optional String username, @Optional @Password String password, @Optional String host, @Optional Integer port, @Optional String database) throws ClassNotFoundException, ExecutionException { Datastore datastore = getDatastore(username, password, database, host, port); QueryBuilder queryBuilder = QueryBuilder.newBuilder(datastore, className).setFilters(filters) .setDisableValidation(disableValidation).setDisableCursorTimeout(disableCursorTimeout) .setDisableSnapshotMode(disableSnapshotMode); boolean exists = datastore.getCount(queryBuilder.getQuery()) > 0; if (exists) { throw getExceptionFromClassName(exception); } } /** * Does the object exists? * <p/> * {@sample.xml ../../../doc/mule-module-morphia.xml.sample morphia:exists-by-id} * * @param id Id of the object to retrieve * @param className Class name of the object to retrieve * @param exception The exception that needs to be thrown if the object does not exist. It must be a RuntimeException. * @param username the username to use in case authentication is required * @param password the password to use in case authentication is required, null * if no authentication is desired * @param host The host of the Mongo server. If the host is part of a replica set then you can specify all the hosts * separated by comma. * @param port The port of the Mongo server * @param database The database name of the Mongo server * @return True if it exists, false otherwise * @throws ExecutionException if there is a connection exception * @throws ClassNotFoundException If the class cannot be found */ @Processor public boolean existsById(String className, Object id, @Optional String exception, @Optional String username, @Optional @Password String password, @Optional String host, @Optional Integer port, @Optional String database) throws ClassNotFoundException, ExecutionException { Datastore datastore = getDatastore(username, password, database, host, port); boolean exists = datastore.exists(new Key(Class.forName(className), id)) != null; if (exception != null && !exists) { throw getExceptionFromClassName(exception); } return exists; } /** * Retrieve an entity (Object) using the specified id * <p/> * {@sample.xml ../../../doc/mule-module-morphia.xml.sample morphia:retrieve} * * @param id Id of the object to retrieve * @param className Class name of the object to retrieve * @param username the username to use in case authentication is required * @param password the password to use in case authentication is required, null * if no authentication is desired * @param host The host of the Mongo server. If the host is part of a replica set then you can specify all the hosts * separated by comma. * @param port The port of the Mongo server * @param database The database name of the Mongo server * @return The retrieve object or null if cannot be found * @throws ExecutionException if there is a connection exception * @throws ClassNotFoundException If the class cannot be found */ @Processor public Object retrieve(String className, Object id, @Optional String username, @Optional @Password String password, @Optional String host, @Optional Integer port, @Optional String database) throws ClassNotFoundException, ExecutionException { Datastore datastore = getDatastore(username, password, database, host, port); return datastore.get(Class.forName(className), id); } /** * Count total objects of the specified class * <p/> * {@sample.xml ../../../doc/mule-module-morphia.xml.sample morphia:count-by-class} * * @param className Class of the object to count * @param username the username to use in case authentication is required * @param password the password to use in case authentication is required, null * if no authentication is desired * @param host The host of the Mongo server. If the host is part of a replica set then you can specify all the hosts * separated by comma. * @param port The port of the Mongo server * @param database The database name of the Mongo server * @throws ExecutionException if there is a connection exception * @return The count * @throws ClassNotFoundException If the class cannot be found */ @Processor public long countByClass(String className, @Optional String username, @Optional @Password String password, @Optional String host, @Optional Integer port, @Optional String database) throws ClassNotFoundException, ExecutionException { Datastore datastore = getDatastore(username, password, database, host, port); return datastore.getCount(Class.forName(className)); } /** * Count total objects using the embedded querying criteria * <p/> * {@sample.xml ../../../doc/mule-module-morphia.xml.sample morphia:count} * * @param className The name of the object class to count * @param filters Filter criteria. Criteria is a composite of the field name and the operator ("field >", or "field in"). All criteria are implicitly combined with a logical "and". * @param disableCursorTimeout Disables cursor timeout on server * @param disableSnapshotMode Disable snapshotted mode (default mode). This will be faster but changes made * during the cursor may cause duplicates. * @param disableValidation Turns off validation * @param username the username to use in case authentication is required * @param password the password to use in case authentication is required, null * if no authentication is desired * @param host The host of the Mongo server. If the host is part of a replica set then you can specify all the hosts * separated by comma. * @param port The port of the Mongo server * @param database The database name of the Mongo server * @throws ExecutionException if there is a connection exception * @return The count * @throws Exception if there is an exception */ @Processor public Object count(String className, @Optional Map<String, Object> filters, @Optional Boolean disableCursorTimeout, @Optional Boolean disableSnapshotMode, @Optional Boolean disableValidation, @Optional String username, @Optional @Password String password, @Optional String host, @Optional Integer port, @Optional String database) throws Exception { Datastore datastore = getDatastore(username, password, database, host, port); QueryBuilder queryBuilder = QueryBuilder.newBuilder(datastore, className); if (disableCursorTimeout != null) { queryBuilder.setDisableCursorTimeout(disableCursorTimeout); } if (disableValidation != null) { queryBuilder.setDisableValidation(disableValidation); } if (disableSnapshotMode != null) { queryBuilder.setDisableSnapshotMode(disableSnapshotMode); } if (filters != null) { queryBuilder.setFilters(filters); } return datastore.getCount(queryBuilder.getQuery()); } /** * Find all instances by type using the specified query criteria * <p/> * {@sample.xml ../../../doc/mule-module-morphia.xml.sample morphia:find} * * @param className Type class name * @param filters Filter criteria. Criteria is a composite of the field name and the operator ("field >", or "field in"). All criteria are implicitly combined with a logical "and". * @param offset Starts the query results at a particular zero-based offset. * @param limit Limit the fetched result set to a certain number of values. * @param order Sorts based on a property (defines return order). * @param fields Limit the returned fields to the ones specified. * @param disableCursorTimeout Disables cursor timeout on server * @param disableSnapshotMode Disable snapshotted mode (default mode). This will be faster but changes made * during the cursor may cause duplicates. * @param disableValidation Turns off validation * @param exception The exception that needs to be thrown if the criteria does not match any result. The exception must be a RuntimeException * @param username the username to use in case authentication is required * @param password the password to use in case authentication is required, null * if no authentication is desired * @param host The host of the Mongo server. If the host is part of a replica set then you can specify all the hosts * separated by comma. * @param port The port of the Mongo server * @param database The database name of the Mongo server * @throws ExecutionException if there is a connection exception * @return An object collection * @throws Exception if there is an exception */ @Processor public Object find(String className, @Optional Map<String, Object> filters, @Optional Integer offset, @Optional Integer limit, @Optional String order, @Optional List<String> fields, @Optional Boolean disableCursorTimeout, @Optional Boolean disableSnapshotMode, @Optional Boolean disableValidation, @Optional String exception, @Optional String username, @Optional @Password String password, @Optional String host, @Optional Integer port, @Optional String database) throws Exception { Datastore datastore = getDatastore(username, password, database, host, port); QueryBuilder queryBuilder = QueryBuilder.newBuilder(datastore, className) .setDisableCursorTimeout(disableCursorTimeout).setDisableValidation(disableValidation) .setDisableSnapshotMode(disableSnapshotMode).setFilters(filters).setOffset(offset).setLimit(limit) .setOrder(order).setFields(fields); List<?> findResult = queryBuilder.getQuery().asList(); if (exception != null && findResult.isEmpty()) { throw getExceptionFromClassName(exception); } return findResult; } /** * Find a single instance of type using the specified query criteria * <p/> * {@sample.xml ../../../doc/mule-module-morphia.xml.sample morphia:find-single} * * @param className Type class name * @param filters Filter criteria. Criteria is a composite of the field name and the operator ("field >", or "field in"). All criteria are implicitly combined with a logical "and". * @param fields Limit the returned fields to the ones specified. * @param disableCursorTimeout Disables cursor timeout on server * @param disableSnapshotMode Disable snapshotted mode (default mode). This will be faster but changes made * during the cursor may cause duplicates. * @param disableValidation Turns off validation * @param exception The exception that needs to be thrown if the criteria does not match any result. The exception must be a RuntimeException * @param username the username to use in case authentication is required * @param password the password to use in case authentication is required, null * if no authentication is desired * @param host The host of the Mongo server. If the host is part of a replica set then you can specify all the hosts * separated by comma. * @param port The port of the Mongo server * @param database The database name of the Mongo server * @throws ExecutionException if there is a connection exception * @return An object collection * @throws Exception if there is an exception */ @Processor public Object findSingle(String className, @Optional Map<String, Object> filters, @Optional List<String> fields, @Optional Boolean disableCursorTimeout, @Optional Boolean disableSnapshotMode, @Optional Boolean disableValidation, @Optional String exception, @Optional String username, @Optional @Password String password, @Optional String host, @Optional Integer port, @Optional String database) throws Exception { Datastore datastore = getDatastore(username, password, database, host, port); QueryBuilder queryBuilder = QueryBuilder.newBuilder(datastore, className) .setDisableCursorTimeout(disableCursorTimeout).setDisableValidation(disableValidation) .setDisableSnapshotMode(disableSnapshotMode).setFilters(filters).setFields(fields); Object findResult = queryBuilder.getQuery().get(); if (exception != null && findResult == null) { throw getExceptionFromClassName(exception); } return findResult; } /** * Find all object ids of type using the specified query criteria * <p/> * {@sample.xml ../../../doc/mule-module-morphia.xml.sample morphia:find-ids} * * @param className Type class name * @param filters Filter criteria. Criteria is a composite of the field name and the operator ("field >", or "field in"). All criteria are implicitly combined with a logical "and". * @param offset Starts the query results at a particular zero-based offset. * @param limit Limit the fetched result set to a certain number of values. * @param order Sorts based on a property (defines return order). * @param disableCursorTimeout Disables cursor timeout on server * @param disableSnapshotMode Disable snapshotted mode (default mode). This will be faster but changes made * during the cursor may cause duplicates. * @param disableValidation Turns off validation * @param username the username to use in case authentication is required * @param password the password to use in case authentication is required, null * if no authentication is desired * @param host The host of the Mongo server. If the host is part of a replica set then you can specify all the hosts * separated by comma. * @param port The port of the Mongo server * @param database The database name of the Mongo server * @throws ExecutionException if there is a connection exception * @return A collection of {@link com.github.jmkgreen.morphia.Key}s * @throws Exception if there is an exception */ @Processor public Object findIds(String className, @Optional Map<String, Object> filters, @Optional Integer offset, @Optional Integer limit, @Optional String order, @Optional Boolean disableCursorTimeout, @Optional Boolean disableSnapshotMode, @Optional Boolean disableValidation, @Optional String username, @Optional @Password String password, @Optional String host, @Optional Integer port, @Optional String database) throws Exception { Datastore datastore = getDatastore(username, password, database, host, port); QueryBuilder queryBuilder = QueryBuilder.newBuilder(datastore, className) .setDisableCursorTimeout(disableCursorTimeout).setDisableValidation(disableValidation) .setDisableSnapshotMode(disableSnapshotMode).setFilters(filters).setOffset(offset).setLimit(limit) .setOrder(order); List<?> result = queryBuilder.getQuery().asKeyList(); if (result.size() == 1) { return result.get(0); } else { return result; } } /** * Deletes the given entity (by id) * <p/> * {@sample.xml ../../../doc/mule-module-morphia.xml.sample morphia:delete-by-id} * * @param className Class of the object to delete * @param id Id of the object to delete * @param username the username to use in case authentication is required * @param password the password to use in case authentication is required, null * if no authentication is desired * @param host The host of the Mongo server. If the host is part of a replica set then you can specify all the hosts * separated by comma. * @param port The port of the Mongo server * @param database The database name of the Mongo server * @throws ExecutionException if there is a connection exception * @return An instance of @{link WriteResult} * @throws ClassNotFoundException If the class cannot be found */ @Processor public WriteResult deleteById(String className, Object id, @Optional String username, @Optional @Password String password, @Optional String host, @Optional Integer port, @Optional String database) throws ClassNotFoundException, ExecutionException { Datastore datastore = getDatastore(username, password, database, host, port); return datastore.delete(Class.forName(className), id); } /** * Deletes the given entity (by @Id) * <p/> * {@sample.xml ../../../doc/mule-module-morphia.xml.sample morphia:delete-single} * * @param object Object to delete * @param username the username to use in case authentication is required * @param password the password to use in case authentication is required, null * if no authentication is desired * @param host The host of the Mongo server. If the host is part of a replica set then you can specify all the hosts * separated by comma. * @param port The port of the Mongo server * @param database The database name of the Mongo server * @throws ExecutionException if there is a connection exception * @return An instance of @{link WriteResult} * @throws Exception if there is an exception */ @Processor public WriteResult deleteSingle(@Optional @Default("#[payload]") Object object, @Optional String username, @Optional @Password String password, @Optional String host, @Optional Integer port, @Optional String database) throws Exception { Datastore datastore = getDatastore(username, password, database, host, port); return datastore.delete(object); } /** * Deletes the given entities based on the query (first item only). * <p/> * {@sample.xml ../../../doc/mule-module-morphia.xml.sample morphia:find-and-delete} * * @param className Type class name * @param filters Filter criteria. Criteria is a composite of the field name and the operator ("field >", or "field in"). All criteria are implicitly combined with a logical "and". * @param offset Starts the query results at a particular zero-based offset. * @param limit Limit the fetched result set to a certain number of values. * @param order Sorts based on a property (defines return order). * @param fields Limit the returned fields to the ones specified. * @param disableCursorTimeout Disables cursor timeout on server * @param disableSnapshotMode Disable snapshot mode (default mode). This will be faster but changes made * during the cursor may cause duplicates. * @param disableValidation Turns off validation * @param exception The exception that needs to be thrown if there is an error on the update or not document is updated or inserted. * @param username the username to use in case authentication is required * @param password the password to use in case authentication is required, null * if no authentication is desired * @param host The host of the Mongo server. If the host is part of a replica set then you can specify all the hosts * separated by comma. * @param port The port of the Mongo server * @param database The database name of the Mongo server * @return the deleted Entity * @throws Exception if there is an exception */ @Processor public Object findAndDelete(String className, @Optional Map<String, Object> filters, @Optional Integer offset, @Optional Integer limit, @Optional String order, @Optional List<String> fields, @Optional Boolean disableCursorTimeout, @Optional Boolean disableSnapshotMode, @Optional Boolean disableValidation, @Optional String exception, @Optional String username, @Optional @Password String password, @Optional String host, @Optional Integer port, @Optional String database) throws Exception { Datastore datastore = getDatastore(username, password, database, host, port); QueryBuilder queryBuilder = QueryBuilder.newBuilder(datastore, className) .setDisableCursorTimeout(disableCursorTimeout).setDisableValidation(disableValidation) .setDisableSnapshotMode(disableSnapshotMode).setFilters(filters).setOffset(offset).setLimit(limit) .setOrder(order).setFields(fields); Object deletedObject = datastore.findAndDelete(queryBuilder.getQuery()); if (deletedObject == null && exception != null) { throw getExceptionFromClassName(exception); } return deletedObject; } /** * Deletes the entities that match the query criteria * <p/> * {@sample.xml ../../../doc/mule-module-morphia.xml.sample morphia:delete} * * @param className Type class name * @param filters Filter criteria. Criteria is a composite of the field name and the operator ("field >", or "field in"). All criteria are implicitly combined with a logical "and". * @param fields Limit the returned fields to the ones specified. * @param disableCursorTimeout Disables cursor timeout on server * @param disableSnapshotMode Disable snapshot mode (default mode). This will be faster but changes made * during the cursor may cause duplicates. * @param disableValidation Turns off validation * @param exception The exception that needs to be thrown if there is an error while deleting * @param username the username to use in case authentication is required * @param password the password to use in case authentication is required, null * if no authentication is desired * @param host The host of the Mongo server. If the host is part of a replica set then you can specify all the hosts * separated by comma. * @param port The port of the Mongo server * @param database The database name of the Mongo server * @throws Exception if there is an exception while deleting */ @Processor public void delete(String className, @Optional Map<String, Object> filters, @Optional List<String> fields, @Optional Boolean disableCursorTimeout, @Optional Boolean disableSnapshotMode, @Optional Boolean disableValidation, @Optional String exception, @Optional String username, @Optional @Password String password, @Optional String host, @Optional Integer port, @Optional String database) throws Exception { Datastore datastore = getDatastore(username, password, database, host, port); QueryBuilder queryBuilder = QueryBuilder.newBuilder(datastore, className) .setDisableCursorTimeout(disableCursorTimeout).setDisableValidation(disableValidation) .setDisableSnapshotMode(disableSnapshotMode).setFilters(filters).setFields(fields); WriteResult writeResult = datastore.delete(queryBuilder.getQuery()); if (!writeResult.getLastError().ok() && exception != null) { throw getExceptionFromClassName(exception); } } /** * Updates the given entity based on the query and the configured operations * * <p/> * {@sample.xml ../../../doc/mule-module-morphia.xml.sample morphia:update} * * @param className Type class name * @param filters Filter criteria. Criteria is a composite of the field name and the operator ("field >", or "field in"). All criteria are implicitly combined with a logical "and". * @param offset Starts the query results at a particular zero-based offset. * @param limit Limit the fetched result set to a certain number of values. * @param disableCursorTimeout Disables cursor timeout on server * @param disableSnapshotMode Disable snapshot mode (default mode). This will be faster but changes made * during the cursor may cause duplicates. * @param disableValidation Turns off validation * @param set sets the fields values * @param unset removes the fields * @param add adds the values to an array field * @param addAll adds multiple values to an array field * @param removeFirst removes first value of the array field * @param removeLast removes last value of the array field * @param remove removes all the given values from the array field using $pull * @param removeAll removes all the given values from the array field using $pullAll * @param allowDups allows duplicates * @param createIfMissing If not found create the entity * @param writeConcern Sets the write concern for this database. It Will be used for writes to any collection in * this database. See the documentation for {@link WriteConcern} for more information. * @param exception The exception that needs to be thrown if there is an error on the update or not document is updated or inserted. * @param username the username to use in case authentication is required * @param password the password to use in case authentication is required, null * if no authentication is desired * @param host The host of the Mongo server. If the host is part of a replica set then you can specify all the hosts * separated by comma. * @param port The port of the Mongo server * @param database The database name of the Mongo server * @return the results of the update * @throws Exception if there is an exception while performing the update */ @SuppressWarnings({ "rawtypes", "unchecked" }) @Processor public UpdateResults update(String className, @Optional Map<String, Object> filters, @Optional Integer offset, @Optional Integer limit, @Optional Boolean disableCursorTimeout, @Optional Boolean disableSnapshotMode, @Optional @Default("false") Boolean disableValidation, @Optional Map<String, Object> set, @Optional List<String> unset, @Optional Map<String, Object> add, @Optional Map<String, List<Object>> addAll, @Optional List<String> removeFirst, @Optional List<String> removeLast, @Optional Map<String, Object> remove, @Optional Map<String, List<Object>> removeAll, @Optional @Default("false") boolean allowDups, @Optional @Default("false") boolean createIfMissing, @Optional @Default("ACKNOWLEDGED") WriteConcern writeConcern, @Optional String exception, @Optional String username, @Optional @Password String password, @Optional String host, @Optional Integer port, @Optional String database) throws Exception { Datastore datastore = getDatastore(username, password, database, host, port); Class entityClass = Class.forName(className); Query query = QueryBuilder.newBuilder(datastore, className).setDisableCursorTimeout(disableCursorTimeout) .setDisableValidation(disableValidation).setDisableSnapshotMode(disableSnapshotMode) .setFilters(filters).setOffset(offset).setLimit(limit).getQuery(); UpdateOperations upOps = datastore.createUpdateOperations(entityClass); if (disableValidation) { upOps.disableValidation(); } if (set != null) { for (String field : set.keySet()) { if (set.get(field) != null) { upOps = upOps.set(field, set.get(field)); } } } if (unset != null) { for (String field : unset) { upOps = upOps.unset(field); } } if (add != null) { for (String field : add.keySet()) { if (add.get(field) != null) { upOps = upOps.add(field, add.get(field), allowDups); } } } if (addAll != null) { for (String field : addAll.keySet()) { if (addAll.get(field) != null) { upOps = upOps.addAll(field, addAll.get(field), allowDups); } } } if (removeFirst != null) { for (String field : removeFirst) { upOps = upOps.removeFirst(field); } } if (removeLast != null) { for (String field : removeLast) { upOps = upOps.removeLast(field); } } if (removeAll != null) { for (String field : removeAll.keySet()) { if (removeAll.get(field) != null) { upOps = upOps.removeAll(field, removeAll.get(field)); } } } if (remove != null) { for (String field : remove.keySet()) { if (remove.get(field) != null) { upOps = upOps.removeAll(field, remove.get(field)); } } } UpdateResults updateResults = datastore.update(query, upOps, createIfMissing, writeConcern.getMongoWriteConcern()); if (exception != null && throwUpdateException(createIfMissing, updateResults)) { throw getExceptionFromClassName(exception); } return updateResults; } /** * Calculates aggregates values without the need for complex map-reduce operations * * <p/> * {@sample.xml ../../../doc/mule-module-morphia.xml.sample morphia:aggregate} * * @param collection collection name * @param pipeline list of pipeline operators * @param exception The exception that needs to be thrown if there is an error executing the aggregation query * @param username the username to use in case authentication is required * @param password the password to use in case authentication is required, null * if no authentication is desired * @param host The host of the Mongo server. If the host is part of a replica set then you can specify all the hosts * separated by comma. * @param port The port of the Mongo server * @param database The database name of the Mongo server * @return the aggregation result * @throws Exception if there is an exception while aggregating */ @Processor public BasicDBList aggregate(String collection, List<Pipeline> pipeline, @Optional String exception, @Optional String username, @Optional @Password String password, @Optional String host, @Optional Integer port, @Optional String database) throws Exception { if (!pipeline.isEmpty()) { Datastore datastore = getDatastore(username, password, database, host, port); List<DBObject> dbObjects = new ArrayList<DBObject>(); for (Pipeline pipelineOperator : pipeline) { Object dbObject = JSON.parse(pipelineOperator.toJson()); if (dbObject == null || !(dbObject instanceof DBObject)) { throw new IllegalArgumentException("Illegal pipeline operator '" + pipelineOperator + "'"); } dbObjects.add((DBObject) dbObject); } BasicDBObjectBuilder builder = BasicDBObjectBuilder.start().add("aggregate", collection); builder.append("pipeline", dbObjects.toArray()); CommandResult result = datastore.getDB().command(builder.get()); if (result.ok()) { return (BasicDBList) result.get("result"); } if (exception != null) { throw getExceptionFromClassName(exception); } } // Return an empty list return new BasicDBList(); } private boolean throwUpdateException(boolean createIfMissing, UpdateResults updateResults) { return (!createIfMissing && !updateResults.getUpdatedExisting()) || (createIfMissing && !updateResults.getUpdatedExisting() && !(updateResults.getInsertedCount() > 0)); } /** * Transform a Morphia object into JSON * <p/> * {@sample.xml ../../../doc/mule-module-morphia.xml.sample morphia:object-to-json} * * @param object Object to transform * @param username the username to use in case authentication is required * @param password the password to use in case authentication is required, null * if no authentication is desired * @param host The host of the Mongo server. If the host is part of a replica set then you can specify all the hosts * separated by comma. * @param port The port of the Mongo server * @param database The database name of the Mongo server * @return A string containing JSON * @throws IOException if there is an exception * @throws ExecutionException if there is a connectivity problem */ @Processor @Mime(MimeTypes.JSON) public String objectToJson(@Optional @Default("#[payload]") Object object, @Optional String username, @Optional @Password String password, @Optional String host, @Optional Integer port, @Optional String database) throws IOException, ExecutionException { Datastore datastore = getDatastore(username, password, database, host, port); if (isListClass(object.getClass())) { if (((List) object).size() == 0) { throw new IllegalArgumentException("The list is empty"); } if (datastore.getMapper().isMapped(((List) object).get(0).getClass())) { List originalList = (List) object; LinkedList<DBObject> dbObjectList = new LinkedList<DBObject>(); for (Object innerObject : originalList) { dbObjectList.addLast(datastore.getMapper().toDBObject(innerObject)); } return JSON.serialize(dbObjectList); } else if (((List) object).get(0) instanceof Key) { List originalList = (List) object; JsonFactory jsonFactory = new JsonFactory(); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); JsonGenerator jsonGenerator = jsonFactory.createJsonGenerator(outputStream); jsonGenerator.writeStartArray(); for (Object innerObject : originalList) { Key keyObject = (Key) innerObject; ObjectId id = (ObjectId) keyObject.getId(); jsonGenerator.writeString(id.toStringMongod()); } jsonGenerator.writeEndArray(); jsonGenerator.flush(); return new String(outputStream.toByteArray()); } else { throw new IllegalArgumentException( ((List) object).get(0).getClass().getName() + " is not a Morphia-mapped type"); } } else if (datastore.getMapper().isMapped(object.getClass())) { return JSON.serialize(datastore.getMapper().toDBObject(object)); } else if (object instanceof Key) { JsonFactory jsonFactory = new JsonFactory(); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); JsonGenerator jsonGenerator = jsonFactory.createJsonGenerator(outputStream); Key keyObject = (Key) object; ObjectId id = (ObjectId) keyObject.getId(); jsonGenerator.writeString(id.toStringMongod()); jsonGenerator.flush(); return new String(outputStream.toByteArray()); } else { throw new IllegalArgumentException(object.getClass().getName() + " is not a Morphia-mapped type"); } } /** * Transform a JSON object into Morphia object * <p/> * {@sample.xml ../../../doc/mule-module-morphia.xml.sample morphia:json-to-object} * * @param className Name of the class representing the type * @param json String containing JSON * @param username the username to use in case authentication is required * @param password the password to use in case authentication is required, null * if no authentication is desired * @param host The host of the Mongo server. If the host is part of a replica set then you can specify all the hosts * separated by comma. * @param port The port of the Mongo server * @param database The database name of the Mongo server * @return The parsed object * @throws ClassNotFoundException if class not found * @throws ExecutionException if there is a connectivity problem */ @Processor public Object jsonToObject(String className, @Optional @Default("#[payload]") String json, @Optional String username, @Optional @Password String password, @Optional String host, @Optional Integer port, @Optional String database) throws ClassNotFoundException, ExecutionException { Datastore datastore = getDatastore(username, password, database, host, port); Object object = JSON.parse(json); if (object == null || !(object instanceof DBObject)) { throw new IllegalArgumentException("Unable to convert JSON string into an object"); } EntityCache entityCache = datastore.getMapper().createEntityCache(); return datastore.getMapper().fromDBObject(Class.forName(className), (DBObject) object, entityCache); } /** * Transforms an entity to a DBRef object * <p/> * {@sample.xml ../../../doc/mule-module-morphia.xml.sample morphia:entity-to-dbref} * * @param entity The entity to transform * @param username the username to use in case authentication is required * @param password the password to use in case authentication is required, null * if no authentication is desired * @param host The host of the Mongo server. If the host is part of a replica set then you can specify all the hosts * separated by comma. * @param port The port of the Mongo server * @param database The database name of the Mongo server * @return The DB Reference * @throws ExecutionException if there is a connectivity problem */ @Processor public DBRef entityToDbref(@Optional @Default("#[payload]") Object entity, @Optional String username, @Optional @Password String password, @Optional String host, @Optional Integer port, @Optional String database) throws ExecutionException { Datastore datastore = getDatastore(username, password, database, host, port); Mapper mapper = datastore.getMapper(); Object id = mapper.getId(entity); if (id == null) { throw new IllegalArgumentException("Could not get id from entity"); } return new DBRef(datastore.getDB(), datastore.getCollection(entity.getClass()).getName(), id); } /** * Returns a DBRef object from a given classname and id * <p/> * {@sample.xml ../../../doc/mule-module-morphia.xml.sample morphia:create-dbref} * * * @param className The class of the DBRef * @param id The ID of the DBRef * @param username the username to use in case authentication is required * @param password the password to use in case authentication is required, null * if no authentication is desired * @param host The host of the Mongo server. If the host is part of a replica set then you can specify all the hosts * separated by comma. * @param port The port of the Mongo server * @param database The database name of the Mongo server * @return The DB Reference * @throws ClassNotFoundException If class not found * @throws ExecutionException If there is a connectivity problem */ @Processor public DBRef createDbref(String className, Object id, @Optional String username, @Optional @Password String password, @Optional String host, @Optional Integer port, @Optional String database) throws ClassNotFoundException, ExecutionException { Datastore datastore = getDatastore(username, password, database, host, port); Mapper mapper = datastore.getMapper(); return new DBRef(datastore.getDB(), datastore.getCollection(Class.forName(className)).getName(), id); } /** * Checks whether the specified class parameter is an instance of {@link List } * * @param clazz <code>Class</code> to check. * @return */ private boolean isListClass(Class clazz) { List<Class> classes = new ArrayList<Class>(); computeClassHierarchy(clazz, classes); return classes.contains(List.class); } /** * Get all superclasses and interfaces recursively. * * @param classes List of classes to which to add all found super classes and interfaces. * @param clazz The class to start the search with. */ private void computeClassHierarchy(Class clazz, List classes) { for (Class current = clazz; (current != null); current = current.getSuperclass()) { if (classes.contains(current)) { return; } classes.add(current); for (Class currentInterface : current.getInterfaces()) { computeClassHierarchy(currentInterface, classes); } } } /** * * Returns an instance of the RuntimeException class name received * * @param className the class name of the RuntimeException * @return an instance of the RuntimeException * @throws ClassNotFoundException if the provided class name does not exist * @throws ExecutionException if there is an error instantiating the class */ private RuntimeException getExceptionFromClassName(String className) throws ClassNotFoundException, ExecutionException { try { Class<? extends RuntimeException> exception = (Class<? extends RuntimeException>) Class .forName(className); return exception.newInstance(); } catch (InstantiationException ie) { throw new ExecutionException("Error getting instance from exception class " + className, ie); } catch (IllegalAccessException iae) { throw new ExecutionException("Error getting instance from exception class " + className, iae); } } private String removeQuotes(String text) { String result = text.trim(); if (result.startsWith("'") || result.startsWith("\"")) { result = result.substring(1, result.length() - 1); } return result; } public List<String> getClasses() { return classes; } public void setClasses(List<String> classes) { this.classes = classes; } public List<String> getPackages() { return packages; } public void setPackages(List<String> packages) { this.packages = packages; } public boolean isIgnoreInvalidClasses() { return ignoreInvalidClasses; } public void setIgnoreInvalidClasses(boolean ignoreInvalidClasses) { this.ignoreInvalidClasses = ignoreInvalidClasses; } public boolean isEnsureIndexesOnBackground() { return ensureIndexesOnBackground; } public void setEnsureIndexesOnBackground(boolean ensureIndexesOnBackground) { this.ensureIndexesOnBackground = ensureIndexesOnBackground; } public Integer getConnectionsPerHost() { return connectionsPerHost; } public void setConnectionsPerHost(Integer connectionsPerHost) { this.connectionsPerHost = connectionsPerHost; } public Integer getThreadsAllowedToBlockForConnectionMultiplier() { return threadsAllowedToBlockForConnectionMultiplier; } public void setThreadsAllowedToBlockForConnectionMultiplier( Integer threadsAllowedToBlockForConnectionMultiplier) { this.threadsAllowedToBlockForConnectionMultiplier = threadsAllowedToBlockForConnectionMultiplier; } public Integer getMaxWaitTime() { return maxWaitTime; } public void setMaxWaitTime(Integer maxWaitTime) { this.maxWaitTime = maxWaitTime; } public Integer getConnectTimeout() { return connectTimeout; } public void setConnectTimeout(Integer connectTimeout) { this.connectTimeout = connectTimeout; } public Integer getSocketTimeout() { return socketTimeout; } public void setSocketTimeout(Integer socketTimeout) { this.socketTimeout = socketTimeout; } public Boolean getAutoConnectRetry() { return autoConnectRetry; } public void setAutoConnectRetry(Boolean autoConnectRetry) { this.autoConnectRetry = autoConnectRetry; } public Boolean getSlaveOk() { return slaveOk; } public void setSlaveOk(Boolean slaveOk) { this.slaveOk = slaveOk; } public Boolean getSafe() { return safe; } public void setSafe(Boolean safe) { this.safe = safe; } public Integer getW() { return w; } public void setW(Integer w) { this.w = w; } public Integer getWtimeout() { return wtimeout; } public void setWtimeout(Integer wtimeout) { this.wtimeout = wtimeout; } public Boolean getFsync() { return fsync; } public void setFsync(Boolean fsync) { this.fsync = fsync; } public String getUsername() { return username; } public String getPassword() { return password; } public String getHost() { return host; } public int getPort() { return port; } public String getDatabase() { return database; } public void setUsername(String username) { this.username = username; } public void setPassword(String password) { this.password = password; } public void setHost(String host) { this.host = host; } public void setPort(int port) { this.port = port; } public void setDatabase(String database) { this.database = database; } }