changeset 1270:11bb959f9814

Refactor Add/Replace/Update to use a generic set(String, Object). Reviewed-by: vanaltj Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2013-October/008360.html PR1569
author Severin Gehwolf <sgehwolf@redhat.com>
date Mon, 30 Sep 2013 17:12:26 +0200
parents 38d89cb2112d
children c43421c64478
files integration-tests/src/test/java/com/redhat/thermostat/itest/MongoQueriesTest.java integration-tests/src/test/java/com/redhat/thermostat/itest/WebAppTest.java main/src/main/resources/com/redhat/thermostat/main/impl/bootstrapbundles.properties storage/core/pom.xml storage/core/src/main/java/com/redhat/thermostat/storage/core/Add.java storage/core/src/main/java/com/redhat/thermostat/storage/core/AddReplaceHelper.java storage/core/src/main/java/com/redhat/thermostat/storage/core/QueuedBackingStorage.java storage/core/src/main/java/com/redhat/thermostat/storage/core/Replace.java storage/core/src/main/java/com/redhat/thermostat/storage/core/Update.java storage/core/src/main/java/com/redhat/thermostat/storage/internal/statement/ParsedStatementImpl.java storage/core/src/main/java/com/redhat/thermostat/storage/internal/statement/PatchedSetListPojoConverter.java storage/core/src/main/java/com/redhat/thermostat/storage/internal/statement/StatementDescriptorParser.java storage/core/src/test/java/com/redhat/thermostat/storage/core/AddReplaceHelperTest.java storage/core/src/test/java/com/redhat/thermostat/storage/internal/statement/ParsedStatementImplTest.java storage/core/src/test/java/com/redhat/thermostat/storage/internal/statement/PatchedSetListPojoConverterTest.java storage/core/src/test/java/com/redhat/thermostat/storage/internal/statement/PreparedStatementImplTest.java storage/mongo/pom.xml storage/mongo/src/main/java/com/redhat/thermostat/storage/mongodb/internal/MongoStorage.java storage/mongo/src/main/java/com/redhat/thermostat/storage/mongodb/internal/MongoUpdate.java storage/mongo/src/test/java/com/redhat/thermostat/storage/mongodb/internal/MongoStorageTest.java
diffstat 20 files changed, 333 insertions(+), 696 deletions(-) [+]
line wrap: on
line diff
--- a/integration-tests/src/test/java/com/redhat/thermostat/itest/MongoQueriesTest.java	Fri Oct 04 14:23:39 2013 +0200
+++ b/integration-tests/src/test/java/com/redhat/thermostat/itest/MongoQueriesTest.java	Mon Sep 30 17:12:26 2013 +0200
@@ -162,7 +162,9 @@
         for (int i = 0; i < numberOfItems; i++) {
             CpuStat pojo = new CpuStat("test-agent-id", i, new double[] {i, i*2});
             Add<CpuStat> add = storage.createAdd(CpuStatDAO.cpuStatCategory);
-            add.setPojo(pojo);
+            add.set(Key.AGENT_ID.getName(), pojo.getAgentId());
+            add.set(CpuStatDAO.cpuLoadKey.getName(), pojo.getPerProcessorUsage());
+            add.set(Key.TIMESTAMP.getName(), pojo.getTimeStamp());
             add.apply();
         }
 
@@ -212,8 +214,7 @@
         pojo.setLoadedClasses(12345);
         pojo.setTimeStamp(42);
         pojo.setVmId(VM_ID1);
-        add.setPojo(pojo);
-        add.apply();
+        addVmClassStat(add, pojo);
         
         // Add another couple of entries
         add = mongoStorage.createAdd(VmClassStatDAO.vmClassStatsCategory);
@@ -222,8 +223,7 @@
         pojo.setLoadedClasses(67890);
         pojo.setTimeStamp(42);
         pojo.setVmId(VM_ID2);
-        add.setPojo(pojo);
-        add.apply();
+        addVmClassStat(add, pojo);
         
         add = mongoStorage.createAdd(VmClassStatDAO.vmClassStatsCategory);
         pojo = new VmClassStat();
@@ -231,12 +231,19 @@
         pojo.setLoadedClasses(34567);
         pojo.setTimeStamp(42);
         pojo.setVmId(VM_ID3);
-        add.setPojo(pojo);
-        add.apply();
+        addVmClassStat(add, pojo);
 
         mongoStorage.getConnection().disconnect();
     }
 
+    private void addVmClassStat(Add<VmClassStat> add, VmClassStat pojo) {
+        add.set(Key.AGENT_ID.getName(), pojo.getAgentId());
+        add.set(Key.VM_ID.getName(), pojo.getVmId());
+        add.set(Key.TIMESTAMP.getName(), pojo.getTimeStamp());
+        add.set(VmClassStatDAO.loadedClassesKey.getName(), pojo.getLoadedClasses());
+        add.apply();
+    }
+
     @Test
     public void canQueryNoWhere() throws Exception {
         CountDownLatch latch = new CountDownLatch(1);
@@ -514,7 +521,10 @@
         double cpuLoad = 0.15;
         VmCpuStat pojo = new VmCpuStat(uuid.toString(), timeStamp, VM_ID1, cpuLoad);
         Add<VmCpuStat> add = mongoStorage.createAdd(VmCpuStatDAO.vmCpuStatCategory);
-        add.setPojo(pojo);
+        add.set(Key.AGENT_ID.getName(), pojo.getAgentId());
+        add.set(Key.VM_ID.getName(), pojo.getVmId());
+        add.set(Key.TIMESTAMP.getName(), pojo.getTimeStamp());
+        add.set(VmCpuStatDAO.vmCpuLoadKey.getName(), pojo.getCpuLoad());
         add.apply();
 
         Query<VmCpuStat> query = mongoStorage.createQuery(VmCpuStatDAO.vmCpuStatCategory);
--- a/integration-tests/src/test/java/com/redhat/thermostat/itest/WebAppTest.java	Fri Oct 04 14:23:39 2013 +0200
+++ b/integration-tests/src/test/java/com/redhat/thermostat/itest/WebAppTest.java	Mon Sep 30 17:12:26 2013 +0200
@@ -407,7 +407,9 @@
         for (int i = 0; i < numberOfItems; i++) {
             CpuStat pojo = new CpuStat("test-agent-id", i, new double[] {i, i*2});
             Add<CpuStat> add = storage.createAdd(CpuStatDAO.cpuStatCategory);
-            add.setPojo(pojo);
+            add.set(Key.AGENT_ID.getName(), pojo.getAgentId());
+            add.set(CpuStatDAO.cpuLoadKey.getName(), pojo.getPerProcessorUsage());
+            add.set(Key.TIMESTAMP.getName(), pojo.getTimeStamp());
             add.apply();
         }
 
@@ -421,7 +423,13 @@
         for (int i = 0; i < numberOfItems; i++) {
             HostInfo hostInfo = new HostInfo("test-host-agent-id", "foo " + i, "linux " + i, "kernel", "t8", i, i * 1000);
             Add<HostInfo> add = storage.createAdd(HostInfoDAO.hostInfoCategory);
-            add.setPojo(hostInfo);
+            add.set(Key.AGENT_ID.getName(), hostInfo.getAgentId());
+            add.set(HostInfoDAO.hostNameKey.getName(), hostInfo.getHostname());
+            add.set(HostInfoDAO.cpuCountKey.getName(), hostInfo.getCpuCount());
+            add.set(HostInfoDAO.cpuModelKey.getName(), hostInfo.getCpuModel());
+            add.set(HostInfoDAO.hostMemoryTotalKey.getName(), hostInfo.getTotalMemory());
+            add.set(HostInfoDAO.osKernelKey.getName(), hostInfo.getOsKernel());
+            add.set(HostInfoDAO.osNameKey.getName(), hostInfo.getOsName());
             add.apply();
         }
 
@@ -434,7 +442,11 @@
 
         for (AgentInformation info: items) {
             Add<AgentInformation> add = storage.createAdd(AgentInfoDAO.CATEGORY);
-            add.setPojo(info);
+            add.set(Key.AGENT_ID.getName(), info.getAgentId());
+            add.set(AgentInfoDAO.ALIVE_KEY.getName(), info.isAlive());
+            add.set(AgentInfoDAO.CONFIG_LISTEN_ADDRESS.getName(), info.getConfigListenAddress());
+            add.set(AgentInfoDAO.START_TIME_KEY.getName(), info.getStartTime());
+            add.set(AgentInfoDAO.STOP_TIME_KEY.getName(), info.getStopTime());
             add.apply();
         }
 
@@ -1070,7 +1082,10 @@
         BackingStorage storage = getAndConnectBackingStorage();
         storage.registerCategory(VmCpuStatDAO.vmCpuStatCategory);
         Add<VmCpuStat> add = storage.createAdd(VmCpuStatDAO.vmCpuStatCategory);
-        add.setPojo(pojo);
+        add.set(Key.AGENT_ID.getName(), pojo.getAgentId());
+        add.set(Key.VM_ID.getName(), pojo.getVmId());
+        add.set(Key.TIMESTAMP.getName(), pojo.getTimeStamp());
+        add.set(VmCpuStatDAO.vmCpuLoadKey.getName(), pojo.getCpuLoad());
         add.apply();
         storage.getConnection().disconnect();        
     }
--- a/main/src/main/resources/com/redhat/thermostat/main/impl/bootstrapbundles.properties	Fri Oct 04 14:23:39 2013 +0200
+++ b/main/src/main/resources/com/redhat/thermostat/main/impl/bootstrapbundles.properties	Mon Sep 30 17:12:26 2013 +0200
@@ -1,14 +1,5 @@
-# FIXME: Remove commons-beanutils, commons-codec, commons-logging,
-#        commons-collections from bootstrap list once storage-core
-#        does no longer depend on beanutils. It has been made
-#        dependent on this because it was required as an interim
-#        measure to switch over to prepared writes.
 bundles=thermostat-shared-config-${project.version}.jar, \
         thermostat-keyring-${project.version}.jar, \
-        commons-codec-${commons-codec.version}.jar, \
-        commons-logging-${commons-logging.version}.jar, \
-        commons-collections-${commons-collections.version}.jar, \
-        commons-beanutils-${commons-beanutils.version}.jar, \
         thermostat-storage-core-${project.version}.jar, \
         thermostat-common-core-${project.version}.jar, \
         thermostat-plugin-validator-${project.version}.jar, \
--- a/storage/core/pom.xml	Fri Oct 04 14:23:39 2013 +0200
+++ b/storage/core/pom.xml	Mon Sep 30 17:12:26 2013 +0200
@@ -106,18 +106,6 @@
       <artifactId>org.apache.felix.framework</artifactId>
     </dependency>
     <dependency>
-      <groupId>commons-beanutils</groupId>
-      <artifactId>commons-beanutils</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>commons-collections</groupId>
-      <artifactId>commons-collections</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>commons-logging</groupId>
-      <artifactId>commons-logging</artifactId>
-    </dependency>
-    <dependency>
       <groupId>com.redhat.thermostat</groupId>
       <artifactId>thermostat-annotations</artifactId>
       <version>${project.version}</version>
--- a/storage/core/src/main/java/com/redhat/thermostat/storage/core/Add.java	Fri Oct 04 14:23:39 2013 +0200
+++ b/storage/core/src/main/java/com/redhat/thermostat/storage/core/Add.java	Mon Sep 30 17:12:26 2013 +0200
@@ -50,11 +50,16 @@
 public interface Add<T extends Pojo> extends DataModifyingStatement<T> {
 
     /**
-     * Sets the POJO that is to be added into storage.
-     *
-     * @param pojo the pojo to be added into storage
+     * Sets a field to the specified value. If the same key is
+     * set more than once, the latest value overrides the former value for that
+     * key.
+     * 
+     * @param key
+     *            the name of the field to update.
+     * @param value
+     *            the value with which to update the field.
      */
-    void setPojo(Pojo pojo);
+    void set(String key, Object value);
 
     /**
      * Applies this {@code Add} operation to storage.
--- a/storage/core/src/main/java/com/redhat/thermostat/storage/core/AddReplaceHelper.java	Fri Oct 04 14:23:39 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-/*
- * Copyright 2012, 2013 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-
-package com.redhat.thermostat.storage.core;
-
-import java.util.Objects;
-
-import com.redhat.thermostat.storage.model.Pojo;
-
-/** Helps in implementing {@link Add} and {@link Replace} classes */
-public abstract class AddReplaceHelper {
-
-    private final Category<?> category;
-    private Pojo pojo;
-    
-    public AddReplaceHelper(Category<?> category) {
-        this.category = Objects.requireNonNull(category);
-    }
-
-    public final Category<?> getCategory() {
-        return category;
-    }
-
-    public final void setPojo(Pojo pojo) {
-        this.pojo = pojo;
-    }
-
-    public final Pojo getPojo() {
-        return pojo;
-    }
-
-}
-
--- a/storage/core/src/main/java/com/redhat/thermostat/storage/core/QueuedBackingStorage.java	Fri Oct 04 14:23:39 2013 +0200
+++ b/storage/core/src/main/java/com/redhat/thermostat/storage/core/QueuedBackingStorage.java	Mon Sep 30 17:12:26 2013 +0200
@@ -72,8 +72,8 @@
         }
 
         @Override
-        public void setPojo(Pojo pojo) {
-            delegateReplace.setPojo(pojo);
+        public void set(String key, Object value) {
+            delegateReplace.set(key, value);
         }
         
     }
@@ -100,8 +100,8 @@
         }
 
         @Override
-        public void setPojo(Pojo pojo) {
-            delegateAdd.setPojo(pojo);
+        public void set(String key, Object value) {
+            delegateAdd.set(key, value);
         }
         
     }
@@ -121,7 +121,7 @@
         }
 
         @Override
-        public <S> void set(Key<S> key, S value) {
+        public void set(String key, Object value) {
             delegateUpdate.set(key, value);
         }
 
--- a/storage/core/src/main/java/com/redhat/thermostat/storage/core/Replace.java	Fri Oct 04 14:23:39 2013 +0200
+++ b/storage/core/src/main/java/com/redhat/thermostat/storage/core/Replace.java	Mon Sep 30 17:12:26 2013 +0200
@@ -59,12 +59,16 @@
 public interface Replace<T extends Pojo> extends DataModifyingStatement<T> {
 
     /**
-     * Sets the POJO that will be used to replace the value in storage.
-     *
-     * @param pojo the pojo which describes the updated values or the new
-     *             record to be added to storage.
+     * Sets a field in a found record to the specified value. If the same key is
+     * set more than once, the latest value overrides the former value for that
+     * key.
+     * 
+     * @param key
+     *            the name of the field to update.
+     * @param value
+     *            the value with which to update the field.
      */
-    void setPojo(Pojo pojo);
+    void set(String key, Object value);
 
     /**
      * Specifies what criteria to use to find the record to replace
--- a/storage/core/src/main/java/com/redhat/thermostat/storage/core/Update.java	Fri Oct 04 14:23:39 2013 +0200
+++ b/storage/core/src/main/java/com/redhat/thermostat/storage/core/Update.java	Mon Sep 30 17:12:26 2013 +0200
@@ -61,14 +61,15 @@
 
     /**
      * Sets a field in a found record to the specified value. If the same key is
-     * set more than once, the latest values overrides the former values.
+     * set more than once, the latest value overrides the former value for that
+     * key.
      * 
      * @param key
-     *            the key of the field
+     *            the name of the field to update.
      * @param value
-     *            the value to set
+     *            the value with which to update the field.
      */
-    <S> void set(Key<S> key, S value);
+    void set(String key, Object value);
 
     /**
      * Applies this update operation.
--- a/storage/core/src/main/java/com/redhat/thermostat/storage/internal/statement/ParsedStatementImpl.java	Fri Oct 04 14:23:39 2013 +0200
+++ b/storage/core/src/main/java/com/redhat/thermostat/storage/internal/statement/ParsedStatementImpl.java	Mon Sep 30 17:12:26 2013 +0200
@@ -38,7 +38,6 @@
 
 import com.redhat.thermostat.storage.core.Add;
 import com.redhat.thermostat.storage.core.IllegalPatchException;
-import com.redhat.thermostat.storage.core.Key;
 import com.redhat.thermostat.storage.core.ParsedStatement;
 import com.redhat.thermostat.storage.core.PreparedParameter;
 import com.redhat.thermostat.storage.core.Query;
@@ -46,7 +45,6 @@
 import com.redhat.thermostat.storage.core.Replace;
 import com.redhat.thermostat.storage.core.Statement;
 import com.redhat.thermostat.storage.core.Update;
-import com.redhat.thermostat.storage.internal.statement.PatchedSetListPojoConverter.IllegalPojoException;
 import com.redhat.thermostat.storage.model.Pojo;
 import com.redhat.thermostat.storage.query.Expression;
 
@@ -60,14 +58,12 @@
 class ParsedStatementImpl<T extends Pojo> implements ParsedStatement<T> {
 
     private final Statement<T> statement;
-    private final Class<T> dataClass; 
     private int numParams;
     private SuffixExpression suffixExpn;
     private SetList setList;
 
-    ParsedStatementImpl(Statement<T> statement, Class<T> dataClass) {
+    ParsedStatementImpl(Statement<T> statement) {
         this.statement = statement;
-        this.dataClass = dataClass;
     }
     
     @Override
@@ -105,35 +101,24 @@
         PatchedSetList patchedSetList = setList.patch(params);
         // set the values
         if (statement instanceof Add) {
-            T pojo = convertToPojo(patchedSetList);
             Add<T> add = (Add<T>)statement;
-            add.setPojo(pojo);
+            for (PatchedSetListMember member: patchedSetList.getSetListMembers()) {
+                add.set(member.getKey().getName(), member.getValue());
+            }
         }
         if (statement instanceof Replace) {
-            T pojo = convertToPojo(patchedSetList);
             Replace<T> replace = (Replace<T>)statement;
-            replace.setPojo(pojo);
+            for (PatchedSetListMember member: patchedSetList.getSetListMembers()) {
+                replace.set(member.getKey().getName(), member.getValue());
+            }
         }
         if (statement instanceof Update) {
             Update<T> update = (Update<T>)statement;
-            for (PatchedSetListMember mem: patchedSetList.getSetListMembers()) {
-                @SuppressWarnings("unchecked")
-                Key<Object> key = (Key<Object>)mem.getKey();
-                update.set(key, mem.getValue());
+            for (PatchedSetListMember member: patchedSetList.getSetListMembers()) {
+                update.set(member.getKey().getName(), member.getValue());
             }
         }
     }
-    
-    private T convertToPojo(PatchedSetList setList) throws IllegalPatchException {
-        PatchedSetListPojoConverter<T> converter = new PatchedSetListPojoConverter<>(setList, dataClass);
-        T pojo = null;
-        try {
-            pojo = converter.convertToPojo();
-        } catch (IllegalPojoException e) {
-            throw new IllegalPatchException(e);
-        }
-        return pojo; 
-    }
 
     private void patchLimit(PreparedParameter[] params) throws IllegalPatchException {
         LimitExpression expn = suffixExpn.getLimitExpn();
--- a/storage/core/src/main/java/com/redhat/thermostat/storage/internal/statement/PatchedSetListPojoConverter.java	Fri Oct 04 14:23:39 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,95 +0,0 @@
-/*
- * Copyright 2012, 2013 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.storage.internal.statement;
-
-import java.beans.PropertyDescriptor;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-
-import org.apache.commons.beanutils.PropertyUtils;
-
-import com.redhat.thermostat.storage.model.Pojo;
-
-class PatchedSetListPojoConverter<T extends Pojo> {
-
-    private final PatchedSetList setList;
-    private final Class<T> dataClass;
-    
-    PatchedSetListPojoConverter(PatchedSetList setList, Class<T> dataClass) {
-        this.setList = setList;
-        this.dataClass = dataClass;
-    }
-    
-    T convertToPojo() throws IllegalPojoException {
-        T instance = null;
-        try {
-            instance = dataClass.newInstance();
-            PatchedSetListMember[] members = setList.getSetListMembers();
-            for (PatchedSetListMember mem: members) {
-                String propName = mem.getKey().getName();
-                PropertyDescriptor desc = PropertyUtils.getPropertyDescriptor(instance, propName);
-                if (desc == null) {
-                    throw new IllegalPojoException("Property " + propName + " not found in Pojo: " + dataClass);
-                }
-                setValueForProperty(instance, desc, mem);
-            }
-        } catch (NoSuchMethodException | InstantiationException | IllegalAccessException
-                | IllegalArgumentException | InvocationTargetException e) {
-            throw new IllegalPojoException(e);
-        }
-        return instance;
-    }
-    
-    private void setValueForProperty(T instance, PropertyDescriptor desc,
-            PatchedSetListMember mem) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
-        Method writeMethod = desc.getWriteMethod();
-        Object value = mem.getValue();
-        writeMethod.invoke(instance, value);
-    }
-
-    @SuppressWarnings("serial")
-    static class IllegalPojoException extends Exception {
-        
-        IllegalPojoException(Throwable cause) {
-            super(cause);
-        }
-        
-        private IllegalPojoException(String msg) {
-            super(msg);
-        }
-    }
-}
--- a/storage/core/src/main/java/com/redhat/thermostat/storage/internal/statement/StatementDescriptorParser.java	Fri Oct 04 14:23:39 2013 +0200
+++ b/storage/core/src/main/java/com/redhat/thermostat/storage/internal/statement/StatementDescriptorParser.java	Mon Sep 30 17:12:26 2013 +0200
@@ -806,31 +806,30 @@
         // matchStatementType and matchCategory advanced currTokenIndex,
         // lets use idx of 0 here.
         final String statementType = tokens[0];
-        Class<T> dataClass = desc.getCategory().getDataClass();
         if (statementType.equals(KNOWN_STATEMENT_TYPES[IDX_QUERY])) {
             // regular query case
             Query<T> query = storage.createQuery(desc.getCategory());
-            this.parsedStatement = new ParsedStatementImpl<>(query, dataClass);
+            this.parsedStatement = new ParsedStatementImpl<>(query);
         } else if (statementType.equals(KNOWN_STATEMENT_TYPES[IDX_QUERY_COUNT])) {
             // create aggregate count query
             Query<T> query = storage.createAggregateQuery(AggregateFunction.COUNT, desc.getCategory());
-            this.parsedStatement = new ParsedStatementImpl<>(query, dataClass);
+            this.parsedStatement = new ParsedStatementImpl<>(query);
         } else if (statementType.equals(KNOWN_STATEMENT_TYPES[IDX_ADD])) {
             // create add
             Add<T> add = storage.createAdd(desc.getCategory());
-            this.parsedStatement = new ParsedStatementImpl<>(add, dataClass);
+            this.parsedStatement = new ParsedStatementImpl<>(add);
         } else if (statementType.equals(KNOWN_STATEMENT_TYPES[IDX_REPLACE])) {
             // create replace
             Replace<T> replace = storage.createReplace(desc.getCategory());
-            this.parsedStatement = new ParsedStatementImpl<>(replace, dataClass);
+            this.parsedStatement = new ParsedStatementImpl<>(replace);
         } else if (statementType.equals(KNOWN_STATEMENT_TYPES[IDX_UPDATE])) {
             // create replace
             Update<T> update = storage.createUpdate(desc.getCategory());
-            this.parsedStatement = new ParsedStatementImpl<>(update, dataClass);
+            this.parsedStatement = new ParsedStatementImpl<>(update);
         } else if (statementType.equals(KNOWN_STATEMENT_TYPES[IDX_REMOVE])) {
             // create remove
             Remove<T> remove = storage.createRemove(desc.getCategory());
-            this.parsedStatement = new ParsedStatementImpl<>(remove, dataClass);
+            this.parsedStatement = new ParsedStatementImpl<>(remove);
         } else {
             throw new IllegalStateException("Don't know how to create statement type '" + statementType + "'");
         }
--- a/storage/core/src/test/java/com/redhat/thermostat/storage/core/AddReplaceHelperTest.java	Fri Oct 04 14:23:39 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-/*
- * Copyright 2012, 2013 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-
-package com.redhat.thermostat.storage.core;
-
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.fail;
-import static org.mockito.Mockito.mock;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import com.redhat.thermostat.storage.model.Pojo;
-
-public class AddReplaceHelperTest {
-    
-    private Category<?> category;
-    
-    @Before
-    public void setup() {
-        category = mock(Category.class);
-    }
-
-    @Test
-    public void testCategory() {
-        TestBasePut insert = new TestBasePut(category);
-
-        assertNotNull(insert.getCategory());
-        assertSame(category, insert.getCategory());
-
-        try {
-            insert = new TestBasePut(null);
-            fail();
-        } catch (NullPointerException ex) {
-            // Ok.
-        }
-    }
-
-    @Test
-    public void testPojo() {
-        Pojo pojo = mock(Pojo.class);
-
-        TestBasePut insert = new TestBasePut(category);
-        assertNull(insert.getPojo());
-        insert.setPojo(pojo);
-        assertSame(pojo, insert.getPojo());
-    }
-    
-    private static class TestBasePut extends AddReplaceHelper {
-
-        public TestBasePut(Category<?> category) {
-            super(category);
-        }
-        
-    }
-}
-
--- a/storage/core/src/test/java/com/redhat/thermostat/storage/internal/statement/ParsedStatementImplTest.java	Fri Oct 04 14:23:39 2013 +0200
+++ b/storage/core/src/test/java/com/redhat/thermostat/storage/internal/statement/ParsedStatementImplTest.java	Mon Sep 30 17:12:26 2013 +0200
@@ -42,7 +42,9 @@
 import static org.junit.Assert.fail;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 import org.junit.After;
 import org.junit.Before;
@@ -85,7 +87,7 @@
     @Test
     public void canPatchWhereAndExpr() throws IllegalPatchException {
         // create the parsedStatementImpl we are going to use
-        ParsedStatementImpl<Pojo> parsedStmt = new ParsedStatementImpl<>(statement, null);
+        ParsedStatementImpl<Pojo> parsedStmt = new ParsedStatementImpl<>(statement);
         SuffixExpression suffixExpn = new SuffixExpression();
         suffixExpn.setLimitExpn(null);
         suffixExpn.setSortExpn(null);
@@ -159,7 +161,7 @@
     @Test
     public void canPatchBasicWhereEquals() throws IllegalPatchException {
         // create the parsedStatementImpl we are going to use
-        ParsedStatementImpl<Pojo> parsedStmt = new ParsedStatementImpl<>(statement, null);
+        ParsedStatementImpl<Pojo> parsedStmt = new ParsedStatementImpl<>(statement);
         SuffixExpression suffixExpn = new SuffixExpression();
         suffixExpn.setLimitExpn(null);
         suffixExpn.setSortExpn(null);
@@ -223,7 +225,7 @@
     @Test
     public void canPatchBasicWhereEqualsLHSKeyAndRHSValue() throws IllegalPatchException {
         // create the parsedStatementImpl we are going to use
-        ParsedStatementImpl<Pojo> parsedStmt = new ParsedStatementImpl<>(statement, null);
+        ParsedStatementImpl<Pojo> parsedStmt = new ParsedStatementImpl<>(statement);
         SuffixExpression suffixExpn = new SuffixExpression();
         suffixExpn.setLimitExpn(null);
         suffixExpn.setSortExpn(null);
@@ -293,7 +295,7 @@
     @Test
     public void canPatchBasicLimit() throws IllegalPatchException {
         // create the parsedStatementImpl we are going to use
-        ParsedStatementImpl<Pojo> parsedStmt = new ParsedStatementImpl<>(statement, null);
+        ParsedStatementImpl<Pojo> parsedStmt = new ParsedStatementImpl<>(statement);
         parsedStmt.setSetList(new SetList());
         SuffixExpression suffixExpn = new SuffixExpression();
         LimitExpression limitExpnToPatch = new LimitExpression();
@@ -354,7 +356,7 @@
     public void canPatchBasicSetListAdd() throws IllegalPatchException {
         // create the parsedStatementImpl we are going to use
         DataModifyingStatement<TestPojo> stmt = new TestAdd<>();
-        ParsedStatementImpl<TestPojo> parsedStmt = new ParsedStatementImpl<>(stmt, TestPojo.class);
+        ParsedStatementImpl<TestPojo> parsedStmt = new ParsedStatementImpl<>(stmt);
         SuffixExpression suffixExpn = new SuffixExpression();
         SetList setList = buildSetList();
         suffixExpn.setLimitExpn(null);
@@ -371,11 +373,10 @@
         Add<TestPojo> add = (Add<TestPojo>)parsedStmt.patchStatement(params);
         assertTrue(add instanceof TestAdd);
         TestAdd<TestPojo> q = (TestAdd<TestPojo>)add;
-        Pojo testPojo = q.pojo;
-        assertTrue(testPojo instanceof TestPojo);
-        TestPojo tPojo = (TestPojo)testPojo;
-        assertEquals("foo-writer", tPojo.getWriterId());
-        assertEquals(Long.MAX_VALUE, tPojo.getFooTimeStamp());
+        Map<String, Object> vals = q.values;
+        assertEquals(2, vals.keySet().size());
+        assertEquals("foo-writer", vals.get("writerId"));
+        assertEquals(Long.MAX_VALUE, vals.get("fooTimeStamp"));
     }
     
     /*
@@ -386,7 +387,7 @@
     public void canPatchSetListAddWithPojoList() throws IllegalPatchException {
         // create the parsedStatementImpl we are going to use
         DataModifyingStatement<FancyPojo> stmt = new TestAdd<>();
-        ParsedStatementImpl<FancyPojo> parsedStmt = new ParsedStatementImpl<>(stmt, FancyPojo.class);
+        ParsedStatementImpl<FancyPojo> parsedStmt = new ParsedStatementImpl<>(stmt);
         SuffixExpression suffixExpn = new SuffixExpression();
         SetList setList = new SetList();
         parsedStmt.setSetList(setList);
@@ -424,14 +425,16 @@
         Add<FancyPojo> add = (Add<FancyPojo>)parsedStmt.patchStatement(params);
         assertTrue(add instanceof TestAdd);
         TestAdd<FancyPojo> q = (TestAdd<FancyPojo>)add;
-        Pojo testPojo = q.pojo;
-        assertTrue(testPojo instanceof FancyPojo);
-        FancyPojo tPojo = (FancyPojo)testPojo;
-        assertEquals(null, tPojo.getWriterId());
-        assertNotNull(tPojo.getSomeList());
-        assertEquals(2, tPojo.getSomeList().length);
-        TestPojo first = tPojo.getSomeList()[0];
-        TestPojo second = tPojo.getSomeList()[1];
+        Map<String, Object> vals = q.values;
+        assertEquals(1, vals.keySet().size());
+        assertEquals(null, vals.get("writerId"));
+        assertNotNull(vals.get("someList"));
+        Object someList = vals.get("someList");
+        assertTrue(someList instanceof TestPojo[]);
+        TestPojo[] tPojo = (TestPojo[])someList;
+        assertEquals(2, tPojo.length);
+        TestPojo first = tPojo[0];
+        TestPojo second = tPojo[1];
         assertEquals(elem1, first);
         assertEquals(elem2, second);
         assertEquals("elem1", first.getWriterId());
@@ -447,7 +450,7 @@
     @Test
     public void canPatchBasicSetListReplace() throws IllegalPatchException {
         DataModifyingStatement<TestPojo> stmt = new TestReplace();
-        ParsedStatementImpl<TestPojo> parsedStmt = new ParsedStatementImpl<>(stmt, TestPojo.class);
+        ParsedStatementImpl<TestPojo> parsedStmt = new ParsedStatementImpl<>(stmt);
         SuffixExpression suffixExpn = new SuffixExpression();
         
         // Build this set list, which corresponds to the TestPojo below
@@ -509,11 +512,10 @@
         Replace<TestPojo> replace = (Replace<TestPojo>)parsedStmt.patchStatement(params);
         assertTrue(replace instanceof TestReplace);
         TestReplace q = (TestReplace)replace;
-        Pojo testPojo = q.pojo;
-        assertTrue(testPojo instanceof TestPojo);
-        TestPojo tPojo = (TestPojo)testPojo;
-        assertEquals("foo-bar", tPojo.getWriterId());
-        assertEquals(Long.MAX_VALUE, tPojo.getFooTimeStamp());
+        Map<String, Object> vals = q.values;
+        assertEquals(2, vals.keySet().size());
+        assertEquals("foo-bar", vals.get("writerId"));
+        assertEquals(Long.MAX_VALUE, vals.get("fooTimeStamp"));
         
         ExpressionFactory factory = new ExpressionFactory();
         Expression expectedExpression = factory.equalTo(new Key<>("foo"), -400);
@@ -527,7 +529,7 @@
     @Test
     public void canPatchBasicSetListUpdate() throws IllegalPatchException {
         DataModifyingStatement<TestPojo> stmt = new TestUpdate();
-        ParsedStatementImpl<TestPojo> parsedStmt = new ParsedStatementImpl<>(stmt, TestPojo.class);
+        ParsedStatementImpl<TestPojo> parsedStmt = new ParsedStatementImpl<>(stmt);
         SuffixExpression suffixExpn = new SuffixExpression();
         
         // Build this set list, which corresponds to the TestPojo below
@@ -579,7 +581,7 @@
         List<Pair<Object, Object>> updates = q.updates;
         assertEquals(1, updates.size());
         Pair<Object, Object> update = updates.get(0);
-        assertEquals(new Key<>("writerId"), update.getFirst());
+        assertEquals("writerId", update.getFirst());
         assertEquals("foobar-writer-id", update.getSecond());
         
         ExpressionFactory factory = new ExpressionFactory();
@@ -590,7 +592,7 @@
     @Test
     public void canPatchBasicSort() throws IllegalPatchException {
         // create the parsedStatementImpl we are going to use
-        ParsedStatementImpl<Pojo> parsedStmt = new ParsedStatementImpl<>(statement, null);
+        ParsedStatementImpl<Pojo> parsedStmt = new ParsedStatementImpl<>(statement);
         parsedStmt.setSetList(new SetList());
         SuffixExpression suffixExpn = new SuffixExpression();
         // SORT ? ASC, b DSC
@@ -635,7 +637,7 @@
     public void failPatchSetListAddWrongType() throws IllegalPatchException {
         // create the parsedStatementImpl we are going to use
         DataModifyingStatement<TestPojo> stmt = new TestAdd<>();
-        ParsedStatementImpl<TestPojo> parsedStmt = new ParsedStatementImpl<>(stmt, TestPojo.class);
+        ParsedStatementImpl<TestPojo> parsedStmt = new ParsedStatementImpl<>(stmt);
         SuffixExpression suffixExpn = new SuffixExpression();
         SetList setList = buildSetList();
         suffixExpn.setLimitExpn(null);
@@ -663,7 +665,7 @@
     public void failPatchSetListAddInsufficientParams() throws IllegalPatchException {
         // create the parsedStatementImpl we are going to use
         DataModifyingStatement<TestPojo> stmt = new TestAdd<>();
-        ParsedStatementImpl<TestPojo> parsedStmt = new ParsedStatementImpl<>(stmt, TestPojo.class);
+        ParsedStatementImpl<TestPojo> parsedStmt = new ParsedStatementImpl<>(stmt);
         SuffixExpression suffixExpn = new SuffixExpression();
         SetList setList = buildSetList();
         suffixExpn.setLimitExpn(null);
@@ -687,7 +689,7 @@
     @Test
     public void failPatchWithWrongType() throws IllegalPatchException {
         // create the parsedStatementImpl we are going to use
-        ParsedStatementImpl<Pojo> parsedStmt = new ParsedStatementImpl<>(statement, null);
+        ParsedStatementImpl<Pojo> parsedStmt = new ParsedStatementImpl<>(statement);
         parsedStmt.setSetList(new SetList());
         SuffixExpression suffixExpn = new SuffixExpression();
         suffixExpn.setLimitExpn(null);
@@ -745,7 +747,7 @@
     @Test
     public void failPatchBasicEqualsIfIndexOutofBounds() {
         // create the parsedStatementImpl we are going to use
-        ParsedStatementImpl<Pojo> parsedStmt = new ParsedStatementImpl<>(statement, null);
+        ParsedStatementImpl<Pojo> parsedStmt = new ParsedStatementImpl<>(statement);
         SuffixExpression suffixExpn = new SuffixExpression();
         suffixExpn.setLimitExpn(null);
         suffixExpn.setSortExpn(null);
@@ -821,11 +823,11 @@
     
     private static class TestAdd<T extends Pojo> implements Add<T> {
         
-        private Pojo pojo; 
+        private Map<String, Object> values = new HashMap<>();
 
         @Override
-        public void setPojo(Pojo pojo) {
-            this.pojo = pojo;
+        public void set(String key, Object value) {
+            values.put(key, value);
         }
 
         @Override
@@ -839,11 +841,11 @@
     private static class TestReplace implements Replace<TestPojo> {
 
         private Expression where;
-        private Pojo pojo;
+        private Map<String, Object> values = new HashMap<>();
         
         @Override
-        public void setPojo(Pojo pojo) {
-            this.pojo = pojo;
+        public void set(String key, Object value) {
+            values.put(key, value);
         }
 
         @Override
@@ -871,7 +873,7 @@
 
         @SuppressWarnings({ "rawtypes", "unchecked" })
         @Override
-        public <S> void set(Key<S> key, S value) {
+        public void set(String key, Object value) {
             Pair update = new Pair<>(key, value);
             updates.add(update);
         }
--- a/storage/core/src/test/java/com/redhat/thermostat/storage/internal/statement/PatchedSetListPojoConverterTest.java	Fri Oct 04 14:23:39 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,142 +0,0 @@
-/*
- * Copyright 2012, 2013 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.storage.internal.statement;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import org.junit.Test;
-
-import com.redhat.thermostat.storage.core.Key;
-import com.redhat.thermostat.storage.internal.statement.PatchedSetListPojoConverter.IllegalPojoException;
-import com.redhat.thermostat.storage.model.Pojo;
-
-public class PatchedSetListPojoConverterTest {
-
-    @Test
-    public void testBasicConversion() throws IllegalPojoException {
-        PatchedSetListMember mem1 = new PatchedSetListMember(new Key<>("foo"), "foo-val");
-        PatchedSetListMember mem2 = new PatchedSetListMember(new Key<>("barKey"), Long.MAX_VALUE);
-        PatchedSetListMember[] members = new PatchedSetListMember[] {
-                mem1,
-                mem2
-        };
-        PatchedSetList setList = mock(PatchedSetList.class);
-        when(setList.getSetListMembers()).thenReturn(members);
-        PatchedSetListPojoConverter<TestMe> converter = new PatchedSetListPojoConverter<>(setList, TestMe.class);
-        TestMe instance = converter.convertToPojo();
-        assertEquals("foo-val", instance.getFoo());
-        assertEquals(Long.MAX_VALUE, instance.getBarKey());
-    }
-    
-    @Test
-    public void testConversionWithLists() throws IllegalPojoException {
-        PatchedSetListMember mem1 = new PatchedSetListMember(new Key<>("foo"), "foo-val");
-        PatchedSetListMember mem2 = new PatchedSetListMember(new Key<>("barKey"), Long.MAX_VALUE);
-        double[] list = new double[] {Math.PI, 3.3};
-        PatchedSetListMember mem3 = new PatchedSetListMember(new Key<>("doubleList"), list);
-        PatchedSetListMember[] members = new PatchedSetListMember[] {
-                mem1,
-                mem2,
-                mem3
-        };
-        PatchedSetList setList = mock(PatchedSetList.class);
-        when(setList.getSetListMembers()).thenReturn(members);
-        PatchedSetListPojoConverter<ListPojo> converter = new PatchedSetListPojoConverter<>(setList, ListPojo.class);
-        ListPojo instance = converter.convertToPojo();
-        assertEquals("foo-val", instance.getFoo());
-        assertEquals(Long.MAX_VALUE, instance.getBarKey());
-        double[] values = instance.getDoubleList();
-        assertEquals(2, values.length);
-        double delta = 0.002;
-        assertEquals(Math.PI, values[0], delta);
-        assertEquals(3.3, values[1], delta);
-    }
-    
-    @Test
-    public void testConversionFailBasic() {
-        PatchedSetListMember mem1 = new PatchedSetListMember(new Key<>("wrong-Prop"), "foo-val");
-        PatchedSetListMember[] members = new PatchedSetListMember[] {
-                mem1
-        };
-        PatchedSetList setList = mock(PatchedSetList.class);
-        when(setList.getSetListMembers()).thenReturn(members);
-        PatchedSetListPojoConverter<TestMe> converter = new PatchedSetListPojoConverter<>(setList, TestMe.class);
-        try {
-            converter.convertToPojo();
-            fail("Should not convert, property not present in Pojo");
-        } catch (IllegalPojoException e) {
-            // pass
-            assertTrue(e.getMessage().contains("Property wrong-Prop not found in Pojo:"));
-        }
-    }
-    
-    public static class TestMe implements Pojo {
-        
-        private String foo;
-        private long barKey;
-
-        public String getFoo() {
-            return foo;
-        }
-        public void setFoo(String foo) {
-            this.foo = foo;
-        }
-        public long getBarKey() {
-            return barKey;
-        }
-        public void setBarKey(long barKey) {
-            this.barKey = barKey;
-        }
-    }
-    
-    public static class ListPojo extends TestMe {
-        
-        private double[] doubleList;
-        
-        public double[] getDoubleList() {
-            return doubleList;
-        }
-        public void setDoubleList(double[] doubleList) {
-            this.doubleList = doubleList;
-        }
-        
-    }
-}
--- a/storage/core/src/test/java/com/redhat/thermostat/storage/internal/statement/PreparedStatementImplTest.java	Fri Oct 04 14:23:39 2013 +0200
+++ b/storage/core/src/test/java/com/redhat/thermostat/storage/internal/statement/PreparedStatementImplTest.java	Mon Sep 30 17:12:26 2013 +0200
@@ -44,7 +44,9 @@
 import static org.mockito.Mockito.when;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 import org.junit.Test;
 
@@ -147,11 +149,10 @@
         } catch (StatementExecutionException e) {
             fail(e.getMessage());
         }
-        assertTrue(add.pojo != null);
-        assertTrue(add.pojo instanceof FooPojo);
+        assertFalse(add.values.isEmpty());
         assertTrue(add.executed);
-        FooPojo fooPojo = (FooPojo)add.pojo;
-        assertEquals("foo-val", fooPojo.getFoo());
+        assertEquals(1, add.values.keySet().size());
+        assertEquals("foo-val", add.values.get("foo"));
     }
     
     @Test
@@ -184,13 +185,13 @@
         } catch (StatementExecutionException e) {
             fail(e.getMessage());
         }
-        assertTrue(add.pojo != null);
-        assertTrue(add.pojo instanceof FancyFoo);
+        assertFalse(add.values.isEmpty());
+        assertEquals(1, add.values.keySet().size());
         assertTrue(add.executed);
-        FancyFoo fooPojo = (FancyFoo)add.pojo;
-        assertEquals(2, fooPojo.getFancyFoo().length);
-        FooPojo first = fooPojo.getFancyFoo()[0];
-        FooPojo second = fooPojo.getFancyFoo()[1];
+        FooPojo[] fancyFoo = (FooPojo[])add.values.get("fancyFoo");
+        assertEquals(2, fancyFoo.length);
+        FooPojo first = fancyFoo[0];
+        FooPojo second = fancyFoo[1];
         assertEquals("one", first.getFoo());
         assertEquals("two", second.getFoo());
     }
@@ -221,8 +222,8 @@
         }
         assertTrue(update.executed);
         assertEquals(1, update.updates.size());
-        Pair<Key<Object>, Object> item = update.updates.get(0);
-        assertEquals(new Key<>("foo"), item.getFirst());
+        Pair<String, Object> item = update.updates.get(0);
+        assertEquals("foo", item.getFirst());
         assertEquals("foo-val", item.getSecond());
         LiteralExpression<Key<String>> o1 = new LiteralExpression<>(new Key<String>("foo"));
         LiteralExpression<String> o2 = new LiteralExpression<>("nice"); 
@@ -255,11 +256,9 @@
         } catch (StatementExecutionException e) {
             fail(e.getMessage());
         }
-        assertTrue(replace.pojo != null);
-        assertTrue(replace.pojo instanceof FooPojo);
+        assertFalse(replace.values.isEmpty());
         assertTrue(replace.executed);
-        FooPojo fooPojo = (FooPojo)replace.pojo;
-        assertEquals("foo-val", fooPojo.getFoo());
+        assertEquals("foo-val", replace.values.get("foo"));
         LiteralExpression<Key<String>> o1 = new LiteralExpression<>(new Key<String>("foo"));
         LiteralExpression<String> o2 = new LiteralExpression<>("bar"); 
         BinaryComparisonExpression<String> binComp = new BinaryComparisonExpression<>(
@@ -324,12 +323,12 @@
     
     private static class TestAdd<T extends Pojo> implements Add<T> {
 
-        private Pojo pojo;
+        private Map<String, Object> values = new HashMap<>();
         private boolean executed = false;
         
         @Override
-        public void setPojo(Pojo pojo) {
-            this.pojo = pojo;
+        public void set(String key, Object value) {
+            values.put(key, value);
         }
 
         @Override
@@ -342,13 +341,13 @@
     
     private static class TestReplace implements Replace<FooPojo> {
 
-        private Pojo pojo;
+        private Map<String, Object> values = new HashMap<>();
         private boolean executed = false;
         private Expression where;
         
         @Override
-        public void setPojo(Pojo pojo) {
-            this.pojo = pojo;
+        public void set(String key, Object value) {
+            values.put(key, value);
         }
 
         @Override
@@ -367,7 +366,7 @@
     private static class TestUpdate implements Update<FooPojo> {
 
         private Expression where;
-        private List<Pair<Key<Object>, Object>> updates = new ArrayList<>();
+        private List<Pair<String, Object>> updates = new ArrayList<>();
         private boolean executed = false;
         
         @Override
@@ -376,9 +375,8 @@
         }
 
         @Override
-        public <S> void set(Key<S> key, S value) {
-            @SuppressWarnings("unchecked")
-            Pair<Key<Object>, Object> item = new Pair<>((Key<Object>) key, (Object)value);
+        public void set(String key, Object value) {
+            Pair<String, Object> item = new Pair<>(key, value);
             updates.add(item);
         }
 
--- a/storage/mongo/pom.xml	Fri Oct 04 14:23:39 2013 +0200
+++ b/storage/mongo/pom.xml	Mon Sep 30 17:12:26 2013 +0200
@@ -87,6 +87,18 @@
       <artifactId>org.apache.felix.framework</artifactId>
     </dependency>
     <dependency>
+      <groupId>commons-beanutils</groupId>
+      <artifactId>commons-beanutils</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>commons-collections</groupId>
+      <artifactId>commons-collections</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>commons-logging</groupId>
+      <artifactId>commons-logging</artifactId>
+    </dependency>
+    <dependency>
       <groupId>org.mongodb</groupId>
       <artifactId>mongo-java-driver</artifactId>
     </dependency>
--- a/storage/mongo/src/main/java/com/redhat/thermostat/storage/mongodb/internal/MongoStorage.java	Fri Oct 04 14:23:39 2013 +0200
+++ b/storage/mongo/src/main/java/com/redhat/thermostat/storage/mongodb/internal/MongoStorage.java	Mon Sep 30 17:12:26 2013 +0200
@@ -37,6 +37,7 @@
 package com.redhat.thermostat.storage.mongodb.internal;
 
 import java.io.InputStream;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -58,7 +59,6 @@
 import com.redhat.thermostat.storage.core.AggregateQuery;
 import com.redhat.thermostat.storage.core.AggregateQuery.AggregateFunction;
 import com.redhat.thermostat.storage.core.BackingStorage;
-import com.redhat.thermostat.storage.core.AddReplaceHelper;
 import com.redhat.thermostat.storage.core.Category;
 import com.redhat.thermostat.storage.core.Connection;
 import com.redhat.thermostat.storage.core.Connection.ConnectionListener;
@@ -67,7 +67,6 @@
 import com.redhat.thermostat.storage.core.DescriptorParsingException;
 import com.redhat.thermostat.storage.core.Key;
 import com.redhat.thermostat.storage.core.PreparedStatement;
-import com.redhat.thermostat.storage.core.PreparedStatementFactory;
 import com.redhat.thermostat.storage.core.Query;
 import com.redhat.thermostat.storage.core.Remove;
 import com.redhat.thermostat.storage.core.Replace;
@@ -99,26 +98,70 @@
             return executeGetCount(category, (MongoQuery<T>)this.queryToAggregate);
         }
     }
+    
+    private static abstract class MongoSetter<T extends Pojo> {
+        
+        protected final DBObject values;
+        protected final Category<T> category;
+        
+        private MongoSetter(Category<T> category) {
+            this.category = category;
+            this.values = new BasicDBObject();
+        }
+        
+        private Object convertPojo(Object value) {
+            // convert pojo values to mongo DB objects if need be
+            if (value instanceof Pojo) {
+                Pojo pojo = (Pojo)value;
+                MongoPojoConverter converter = new MongoPojoConverter();
+                value = converter.convertPojoToMongo(pojo);
+            } else if (value instanceof Pojo[]) {
+                List<DBObject> pojos = new ArrayList<>();
+                MongoPojoConverter converter = new MongoPojoConverter();
+                Pojo[] list = (Pojo[])value;
+                for (Pojo p: list) {
+                    DBObject converted = converter.convertPojoToMongo(p);
+                    pojos.add(converted);
+                }
+                value = pojos;
+            }
+            return value;
+        }
+        
+        protected void set(String key, Object value) {
+            // convert Pojo/list of Pojos to DBObject/list of DBObjects
+            // if need be
+            value = convertPojo(value);
+            values.put(key, value);
+        }
+    }
 
-    private class MongoAdd<T extends Pojo> extends AddReplaceHelper implements Add<T> {
-
-        private MongoAdd(Category<?> category) {
+    private class MongoAdd<T extends Pojo> extends MongoSetter<T>
+            implements Add<T> {
+        
+        private MongoAdd(Category<T> category) {
             super(category);
         }
         
         @Override
         public int apply() {
-            return addImpl(getCategory(), getPojo());
+            return addImpl(category, values);
+        }
+
+        @Override
+        public void set(String key, Object value) {
+            super.set(key, value);
         }
         
     }
 
-    private class MongoReplace<T extends Pojo> extends AddReplaceHelper implements Replace<T> {
+    private class MongoReplace<T extends Pojo> extends MongoSetter<T>
+            implements Replace<T> {
         
         private DBObject query;
         private final MongoExpressionParser parser;
 
-        private MongoReplace(Category<?> category) {
+        private MongoReplace(Category<T> category) {
             super(category);
             this.parser = new MongoExpressionParser();
         }
@@ -130,28 +173,62 @@
                              "Please call where() before apply().";
                 throw new IllegalStateException(msg);
             }
-            return replaceImpl(getCategory(), getPojo(), query);
+            return replaceImpl(category, values, query);
         }
 
         @Override
         public void where(Expression expression) {
             this.query = parser.parse(Objects.requireNonNull(expression));
         }
+
+        @Override
+        public void set(String key, Object value) {
+            super.set(key, value);
+        }
         
     }
     
+    private class MongoUpdate<T extends Pojo> extends MongoSetter<T>
+            implements Update<T> {
+
+        private static final String SET_MODIFIER = "$set";
+
+        private DBObject query;
+        private final MongoExpressionParser parser;
+
+        private MongoUpdate(Category<T> category) {
+            super(category);
+            this.parser = new MongoExpressionParser();
+        }
+
+        @Override
+        public void where(Expression expr) {
+            query = parser.parse(expr);
+        }
+
+        @Override
+        public void set(String key, Object value) {
+            super.set(key, value);
+        }
+
+        @Override
+        public int apply() {
+            DBObject setValues = new BasicDBObject(SET_MODIFIER, values);
+            return updateImpl(category, setValues, query);
+        }
+    }
+    
     private class MongoRemove<T extends Pojo> implements Remove<T> {
 
-        @SuppressWarnings("rawtypes")
-        private final Category category;
+        private final Category<T> category;
         private DBObject query;
         private final MongoExpressionParser parser;
         
-        private MongoRemove(Category<?> category) {
+        private MongoRemove(Category<T> category) {
             this(category, new MongoExpressionParser());
         }
         
-        private MongoRemove(Category<?> category, MongoExpressionParser parser) {
+        private MongoRemove(Category<T> category, MongoExpressionParser parser) {
             this.parser = parser;
             this.category = category;
         }
@@ -229,17 +306,17 @@
         return replace;
     }
 
-    private int addImpl(final Category<?> cat, final Pojo pojo) {
+    private <T extends Pojo> int addImpl(final Category<T> cat, final DBObject values) {
         DBCollection coll = getCachedCollection(cat);
-        DBObject toInsert = preparePut(pojo);
-        WriteResult result = coll.insert(toInsert);
+        assertContainsWriterID(values);
+        WriteResult result = coll.insert(values);
         return numAffectedRecords(result);
     }
 
-    private int replaceImpl(final Category<?> cat, final Pojo pojo, final DBObject query) {
+    private <T extends Pojo> int replaceImpl(final Category<T> cat, final DBObject values, final DBObject query) {
         DBCollection coll = getCachedCollection(cat);
-        DBObject toInsert = preparePut(pojo);
-        WriteResult result = coll.update(query, toInsert, true, false);
+        assertContainsWriterID(values);
+        WriteResult result = coll.update(query, values, true, false);
         return numAffectedRecords(result);
     }
     
@@ -249,21 +326,14 @@
         return responseCode;
     }
 
-    private DBObject preparePut(final Pojo pojo) {
-        MongoPojoConverter converter = new MongoPojoConverter();
-        DBObject toInsert = converter.convertPojoToMongo(pojo);
-        if (toInsert.get(Key.AGENT_ID.getName()) == null) {
-            // FIXME: Remove
-            throw new AssertionError("agentID must be set");
+    private void assertContainsWriterID(final DBObject values) {
+        if (values.get(Key.AGENT_ID.getName()) == null) {
+            throw new AssertionError("agentId must be set");
         }
-        return toInsert;
     }
 
-    int updatePojo(MongoUpdate<?> mongoUpdate) {
-        Category<?> cat = mongoUpdate.getCategory();
-        DBCollection coll = getCachedCollection(cat);
-        DBObject query = mongoUpdate.getQuery();
-        DBObject values = mongoUpdate.getValues();
+    private <T extends Pojo> int updateImpl(Category<T> category, DBObject values, DBObject query) {
+        DBCollection coll = getCachedCollection(category);
         WriteResult result = coll.update(query, values);
         return numAffectedRecords(result);
     }
@@ -339,7 +409,7 @@
 
     @Override
     public <T extends Pojo> Update<T> createUpdate(Category<T> category) {
-        return new MongoUpdate<>(this, category);
+        return new MongoUpdate<>(category);
     }
 
     @Override
--- a/storage/mongo/src/main/java/com/redhat/thermostat/storage/mongodb/internal/MongoUpdate.java	Fri Oct 04 14:23:39 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,98 +0,0 @@
-/*
- * Copyright 2012, 2013 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-
-package com.redhat.thermostat.storage.mongodb.internal;
-
-import com.mongodb.BasicDBObject;
-import com.mongodb.DBObject;
-import com.redhat.thermostat.storage.core.Category;
-import com.redhat.thermostat.storage.core.Key;
-import com.redhat.thermostat.storage.core.Update;
-import com.redhat.thermostat.storage.model.Pojo;
-import com.redhat.thermostat.storage.query.Expression;
-
-class MongoUpdate<T extends Pojo> implements Update<T> {
-
-    private static final String SET_MODIFIER = "$set";
-
-    private MongoStorage storage;
-    private DBObject query;
-    private DBObject values;
-    private Category<?> category;
-    private MongoExpressionParser parser;
-
-    public MongoUpdate(MongoStorage storage, Category<?> category) {
-        this(storage, category, new MongoExpressionParser());
-    }
-    
-    MongoUpdate(MongoStorage storage, Category<?> category, MongoExpressionParser parser) {
-        this.storage = storage;
-        this.category = category;
-        this.parser = parser;
-    }
-
-    Category<?> getCategory() {
-        return category;
-    }
-
-    @Override
-    public void where(Expression expr) {
-        query = parser.parse(expr);
-    }
-
-    DBObject getQuery() {
-        return query;
-    }
-
-    @Override
-    public <S> void set(Key<S> key, S value) {
-        if (values == null) {
-            values = new BasicDBObject();
-        }
-        values.put(key.getName(), value);
-    }
-
-    DBObject getValues() {
-        return new BasicDBObject(SET_MODIFIER, values);
-    }
-
-    @Override
-    public int apply() {
-        return storage.updatePojo(this);
-    }
-}
-
--- a/storage/mongo/src/test/java/com/redhat/thermostat/storage/mongodb/internal/MongoStorageTest.java	Fri Oct 04 14:23:39 2013 +0200
+++ b/storage/mongo/src/test/java/com/redhat/thermostat/storage/mongodb/internal/MongoStorageTest.java	Mon Sep 30 17:12:26 2013 +0200
@@ -56,6 +56,7 @@
 import java.io.InputStream;
 import java.lang.reflect.Field;
 import java.util.LinkedHashSet;
+import java.util.List;
 import java.util.Set;
 import java.util.concurrent.CountDownLatch;
 
@@ -168,7 +169,7 @@
     private static final Key<String> key4 = new Key<>("key4");
     private static final Key<String> key5 = new Key<>("key5");
     private static final Category<TestClass> testCategory = new Category<>("MongoStorageTest", TestClass.class, key1, key2, key3, key4, key5);
-    private static final Category<TestClass> emptyTestCategory = new Category("MongoEmptyCategory", TestClass.class);
+    private static final Category<TestClass> emptyTestCategory = new Category<>("MongoEmptyCategory", TestClass.class);
 
     private StartupConfiguration conf;
     private Mongo m;
@@ -264,7 +265,7 @@
     @Test
     public void verifyFindAllReturnsCursor() throws Exception {
         MongoStorage storage = makeStorage();
-        Query query = storage.createQuery(testCategory);
+        Query<TestClass> query = storage.createQuery(testCategory);
         Cursor<TestClass> cursor = query.execute();
         assertNotNull(cursor);
     }
@@ -272,7 +273,7 @@
     @Test
     public void verifyFindAllCallsDBCollectionFind() throws Exception {
         MongoStorage storage = makeStorage();
-        Query query = storage.createQuery(testCategory);
+        Query<TestClass> query = storage.createQuery(testCategory);
         ExpressionFactory factory = new ExpressionFactory();
         Expression expr = factory.equalTo(key1, "fluff");
         query.where(expr);
@@ -284,7 +285,8 @@
     public void verifyFindAllCallsDBCollectionFindWithCorrectQuery() throws Exception {
         MongoStorage storage = makeStorage();
 
-        MongoQuery query = mock(MongoQuery.class);
+        @SuppressWarnings("unchecked")
+        MongoQuery<TestClass> query = mock(MongoQuery.class);
         when(query.hasClauses()).thenReturn(true);
         DBObject generatedQuery = mock(DBObject.class);
         when(query.getGeneratedQuery()).thenReturn(generatedQuery);
@@ -300,7 +302,7 @@
         MongoStorage storage = makeStorage();
         // TODO find a way to test this that isn't just testing MongoCursor
         // Because we mock the DBCollection, the contents of this query don't actually determine the result.
-        Query query = storage.createQuery(testCategory);
+        Query<TestClass> query = storage.createQuery(testCategory);
         Cursor<TestClass> cursor = query.execute();
 
         verifyDefaultCursor(cursor);
@@ -311,7 +313,7 @@
         MongoStorage storage = makeStorage();
         // TODO find a way to test this that isn't just testing MongoCursor
         // Because we mock the DBCollection, the contents of this query don't actually determine the result.
-        Query query = storage.createQuery(testCategory);
+        Query<TestClass> query = storage.createQuery(testCategory);
         query.sort(key1, Query.SortDirection.ASCENDING);
         query.limit(3);
 
@@ -328,7 +330,7 @@
     @Test
     public void verifyFindAllFromCategoryCallsDBCollectionFindAll() throws Exception {
         MongoStorage storage = makeStorage();
-        Query query = storage.createQuery(testCategory);
+        Query<TestClass> query = storage.createQuery(testCategory);
         query.execute();
         verify(testCollection).find();
     }
@@ -336,7 +338,7 @@
     @Test
     public void verifyFindAllFromCategoryReturnsCorrectCursor() throws Exception {
         MongoStorage storage = makeStorage();
-        Query query = storage.createQuery(testCategory);
+        Query<TestClass> query = storage.createQuery(testCategory);
         Cursor<TestClass> cursor = query.execute();
 
         verifyDefaultCursor(cursor);
@@ -377,31 +379,76 @@
         MongoStorage storage = makeStorage();
         TestClass pojo = new TestClass();
         pojo.setAgentId("123");
-        Add add = storage.createAdd(testCategory);
-        add.setPojo(pojo);
+        Add<TestClass> add = storage.createAdd(testCategory);
+        add.set(Key.AGENT_ID.getName(), pojo.getAgentId());
         add.apply();
         ArgumentCaptor<DBObject> dbobj = ArgumentCaptor.forClass(DBObject.class);
         verify(testCollection).insert(dbobj.capture());
         DBObject val = dbobj.getValue();
         assertEquals("123", val.get("agentId"));
     }
+    
+    /*
+     *  This test verifies if pojo types get converted correctly. This
+     *  add isn't really using the correct type parameter. It should be using
+     *  a pojo which has itself Pojo properties defined. For the sake of this
+     *  test this "hack" should be sufficient.
+     */
+    @Test
+    public void verifyPojoTypeGetsConverted() throws Exception {
+        MongoStorage storage = makeStorage();
+        TestClass pojo = new TestClass();
+        pojo.setKey1("val1");
+        pojo.setKey3("val3");
+        Add<?> add = storage.createAdd(testCategory);
+        add.set("agentId", "ignored");
+        add.set("foo-pojo-key", pojo);
+        add.apply();
+        ArgumentCaptor<DBObject> dbobj = ArgumentCaptor.forClass(DBObject.class);
+        verify(testCollection).insert(dbobj.capture());
+        DBObject val = dbobj.getValue();
+        assertTrue(val.get("foo-pojo-key") instanceof DBObject);
+        DBObject pojoVal = (DBObject)val.get("foo-pojo-key");
+        assertEquals("val1", pojoVal.get("key1"));
+        assertEquals("val3", pojoVal.get("key3"));
+    }
+    
+    @Test
+    public void verifyPojoListGetsConverted() throws Exception {
+        MongoStorage storage = makeStorage();
+        TestClass pojo = new TestClass();
+        pojo.setKey1("val1");
+        pojo.setKey3("val3");
+        TestClass[] list = new TestClass[] { pojo };
+        Add<?> add = storage.createAdd(testCategory);
+        add.set("agentId", "ignored");
+        add.set("foo-pojo-key", list);
+        add.apply();
+        ArgumentCaptor<DBObject> dbobj = ArgumentCaptor.forClass(DBObject.class);
+        verify(testCollection).insert(dbobj.capture());
+        DBObject val = dbobj.getValue();
+        assertTrue(val.get("foo-pojo-key") instanceof List);
+        @SuppressWarnings("unchecked")
+        List<DBObject> result = (List<DBObject>)val.get("foo-pojo-key");
+        assertEquals(1, result.size());
+        DBObject pojoVal = result.get(0);
+        assertEquals("val1", pojoVal.get("key1"));
+        assertEquals("val3", pojoVal.get("key3"));
+    }
 
     @Test
     public void verifyPutChunkDoesNotUseGlobalAgent() throws Exception {
         MongoStorage storage = makeStorage();
-        TestClass pojo = new TestClass();
-        Add add = storage.createAdd(testCategory);
-        add.setPojo(pojo);
+        Add<TestClass> add = storage.createAdd(testCategory);
         try {
             add.apply();
             fail("We do not allow null agentId");
         } catch (AssertionError e) {
             // pass
         }
-        Replace replace = storage.createReplace(testCategory);
+        Replace<TestClass> replace = storage.createReplace(testCategory);
         ExpressionFactory factory = new ExpressionFactory();
         Expression whereExp = factory.equalTo(Key.AGENT_ID, "foobar");
-        replace.setPojo(pojo);
         replace.where(whereExp);
         try {
             replace.apply();
@@ -431,10 +478,10 @@
     @Test
     public void verifySimpleUpdate() {
         MongoStorage storage = makeStorage();
-        Update update = storage.createUpdate(testCategory);
+        Update<TestClass> update = storage.createUpdate(testCategory);
         Expression expr = factory.equalTo(Key.AGENT_ID, "test1");
         update.where(expr);
-        update.set(key2, "test2");
+        update.set(key2.getName(), "test2");
         update.apply();
 
         ArgumentCaptor<DBObject> queryCaptor = ArgumentCaptor.forClass(DBObject.class);
@@ -457,11 +504,11 @@
     @Test
     public void verifyMultiFieldUpdate() {
         MongoStorage storage = makeStorage();
-        Update update = storage.createUpdate(testCategory);
+        Update<TestClass> update = storage.createUpdate(testCategory);
         Expression expr = factory.equalTo(Key.AGENT_ID, "test1");
         update.where(expr);
-        update.set(key2, "test2");
-        update.set(key3, "test3");
+        update.set(key2.getName(), "test2");
+        update.set(key3.getName(), "test3");
         update.apply();
 
         ArgumentCaptor<DBObject> queryCaptor = ArgumentCaptor.forClass(DBObject.class);
@@ -492,13 +539,18 @@
         pojo.setKey5("test5");
 
         MongoStorage storage = makeStorage();
-        Replace replace = storage.createReplace(testCategory);
+        Replace<TestClass> replace = storage.createReplace(testCategory);
         ExpressionFactory factory = new ExpressionFactory();
         Expression first = factory.equalTo(key1, "test1");
         Expression second = factory.equalTo(key2, "test2");
         Expression and = factory.and(first, second);
         replace.where(and);
-        replace.setPojo(pojo);
+        replace.set("key1", pojo.getKey1());
+        replace.set("key2", pojo.getKey2());
+        replace.set("key3", pojo.getKey3());
+        replace.set("key4", pojo.getKey4());
+        replace.set("key5", pojo.getKey5());
+        replace.set(Key.AGENT_ID.getName(), pojo.getAgentId());
         replace.apply();
 
         ArgumentCaptor<DBObject> queryCaptor = ArgumentCaptor.forClass(DBObject.class);