Displaying differences for changeset
 
display as  

src/java/m/wqm/nutappmgtscores/V1_0.java

@@ -22,16 +22,17 @@
 import org.codehaus.jettison.json.JSONObject;
 import java.util.concurrent.TimeUnit;
 import java.util.logging.Level;
-import java.util.logging.Logger;
 import org.codehaus.jettison.json.JSONException;
 import wqm.utils.DBResources;
 import static wqm.utils.DBResources.WQM_ID;
 
 @Name("WQM-16: Nutrient Application Management Scores (NutAppMgtScores)")
-@Description("This service computes scores for adjusting the rate, timing, and method of applying nutrients to mitigate nitrogen leaching, and nitrogen and phosphorus runoff loss potential.")
+@Description("This service computes scores for adjusting the rate, timing, "
+        + "and method of applying nutrients to mitigate nitrogen leaching, "
+        + "and nitrogen and phosphorus runoff loss potential.")
 @Path("m/nutappmgtscores/1.0")
 @Polling(first = 10000, next = 2000)
-@Resource( from = DBResources.class)
+@Resource(from = DBResources.class)
 public class V1_0 extends ModelDataService {
 
     //Response
@@ -45,641 +46,670 @@
 
     @Override
     protected void preProcess() throws Exception {
+        try {
+            AoAId = getIntParam("aoa_id", 0);
+            p_soil_test_result = getStringParam("p_soil_test_result", "err");
+            cropList = new ArrayList<>();
 
-    
-        AoAId = getIntParam("aoa_id", 0);
-        p_soil_test_result = getStringParam("p_soil_test_result", "err");
-        cropList = new ArrayList<>();
+            JSONArray cropIds = getJSONArrayParam("cropIds");
+            for (int i = 0; i < cropIds.length(); i++) {
+                JSONArray applicationList = null;
+                Map<String, JSONObject> mgtCropId = JSONUtils.preprocess(cropIds.getJSONArray(i));
 
-        JSONArray cropIds = getJSONArrayParam("cropIds");
-        for (int i = 0; i < cropIds.length(); i++) {
-        JSONArray applicationList = null;
-        Map<String, JSONObject> mgtCropId = JSONUtils.preprocess(cropIds.getJSONArray(i));
+                if (JSONUtils.checkKeyExistsB(mgtCropId, "applicationList")) {
+                    applicationList = JSONUtils.getJSONArrayParam(mgtCropId, "applicationList");
+                }
 
-        if (JSONUtils.checkKeyExistsB(mgtCropId, "applicationList")) {
-            applicationList = JSONUtils.getJSONArrayParam(mgtCropId, "applicationList");
-        }
+                cropList.add(new Crop(JSONUtils.getIntParam(mgtCropId, "mgt_crop_id", 0), JSONUtils.getStringParam(mgtCropId, "crop_plant_date", "err"),
+                        JSONUtils.getDoubleParam(mgtCropId, "crop_yield", 0), JSONUtils.getStringParam(mgtCropId, "crop_yield_units", "err"),
+                        applicationList, p_soil_test_result));
+            }
+        } catch (ServiceException | JSONException ex) {
+            LOG.log(Level.SEVERE, "Error in processing the request JSON for WQM-16!", ex);
+            throw new ServiceException("Error in processing the request JSON.", ex);
+        }
 
-        cropList.add(new Crop(JSONUtils.getIntParam(mgtCropId, "mgt_crop_id", 0), JSONUtils.getStringParam(mgtCropId, "crop_plant_date", "err"),
-            JSONUtils.getDoubleParam(mgtCropId, "crop_yield", 0), JSONUtils.getStringParam(mgtCropId, "crop_yield_units", "err"),
-            applicationList, p_soil_test_result));
-        }
+        ValidateInput();
 
-        ValidateInput();
-    
     }
 
     @Override
     protected void doProcess() throws Exception {
-    String ret_val = EXEC_OK;
-    int n_app_timing_score = 100;
-    int p_app_timing_score = 100;
-    int app_method_score = -1;
-    int n_app_rate_score = 0;
-    int p_app_rate_score = 0;
-    int this_crop_id = 0;
-    String query;
-    
-    if (!error_msg.isEmpty()) {
-        ret_val = error_msg;
-    } else {
-        result = new ArrayList<>();
+        String ret_val = EXEC_OK;
+        int n_app_timing_score = 100;
+        int p_app_timing_score = 100;
+        int app_method_score = -1;
+        int n_app_rate_score = 0;
+        int p_app_rate_score = 0;
+        int this_crop_id = 0;
+        String query;
 
-     try (Connection conn = getResourceJDBC(WQM_ID);
-                Statement statement = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY)) {
-        for (Crop crop : cropList) {
+        if (!error_msg.isEmpty()) {
+            ret_val = error_msg;
+        } else {
+            result = new ArrayList<>();
 
-            String crop_type = crop.getCropType();
-//////TODO:  Remember to check for errors from the classes....   ///////                    
-            if (!crop_type.isEmpty()) {
-            //#Update N and P application management rate scores for each crop
-            int[] app_rate_scores = crop.getNutrientApplicationRateScores();
-            if (!(error_msg = crop.getErrorMsg()).isEmpty()) {
-                break;
-            }
+            try (Connection conn = getResourceJDBC(WQM_ID);
+                    Statement statement = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
+                            ResultSet.CONCUR_READ_ONLY)) {
+                for (Crop crop : cropList) {
 
-            //Cummulative sum of N and P application management scores over all crops for the AoA
-            n_app_rate_score += app_rate_scores[Crop.N_APP_RATE_SCORE];
-            p_app_rate_score += app_rate_scores[Crop.P_APP_RATE_SCORE];
+                    String crop_type = crop.getCropType();
+//////TODO:  Remember to check for errors from the classes....   ///////
+                    if (!crop_type.isEmpty()) {
+                        //#Update N and P application management rate scores for each crop
+                        int[] app_rate_scores = crop.getNutrientApplicationRateScores();
+                        if (!(error_msg = crop.getErrorMsg()).isEmpty()) {
+                            break;
+                        }
 
-            //#Compute N and P application timing scores for the crop and update timing scores for the AoA
-            int[] app_time_scores = crop.getNutrientApplicationTimingScores();
-            if (!(error_msg = crop.getErrorMsg()).isEmpty()) {
-                break;
-            }
+                        //Cummulative sum of N and P application management scores over all crops for the AoA
+                        n_app_rate_score += app_rate_scores[Crop.N_APP_RATE_SCORE];
+                        p_app_rate_score += app_rate_scores[Crop.P_APP_RATE_SCORE];
+
+                        //#Compute N and P application timing scores for the crop and update timing scores for the AoA
+                        int[] app_time_scores = crop.getNutrientApplicationTimingScores();
+                        if (!(error_msg = crop.getErrorMsg()).isEmpty()) {
+                            break;
+                        }
 
                         //  There is a problem with the logic of the specification here...It does not take into account the actual timing of applications when
-            //  there are mulitple crops and multiple years invovled....these final values are probably not correct.  The "-1" below is placed here
-            //  in an attempt to fix the missing database values problem that also exists with this logic at the nutrient level.
-            if ((app_time_scores[Crop.N_APP_TIMING_SCORE] < n_app_timing_score) || (n_app_timing_score == -1)) {
-                n_app_timing_score = app_time_scores[Crop.N_APP_TIMING_SCORE];
-            }
+                        //  there are mulitple crops and multiple years invovled....these final values are probably not correct.  The "-1" below is placed here
+                        //  in an attempt to fix the missing database values problem that also exists with this logic at the nutrient level.
+                        if ((app_time_scores[Crop.N_APP_TIMING_SCORE] < n_app_timing_score) || (n_app_timing_score == -1)) {
+                            n_app_timing_score = app_time_scores[Crop.N_APP_TIMING_SCORE];
+                        }
 
-            if ((app_time_scores[Crop.P_APP_TIMING_SCORE] < p_app_timing_score) || (p_app_timing_score == -1)) {
-                p_app_timing_score = app_time_scores[Crop.P_APP_TIMING_SCORE];
-            }
+                        if ((app_time_scores[Crop.P_APP_TIMING_SCORE] < p_app_timing_score) || (p_app_timing_score == -1)) {
+                            p_app_timing_score = app_time_scores[Crop.P_APP_TIMING_SCORE];
+                        }
 
-            //#If any nutrient application for any crop is not incorporated, the method score for the AoA is zero
-            if (!crop.allNutrientsIncorporated()) {
-                app_method_score = 0;
-            }
-            if (!(error_msg = crop.getErrorMsg()).isEmpty()) {
-                break;
-            }
-            } else {
-            ret_val = error_msg = "Cannot get crop_type. " + crop.getErrorMsg();
-            }
-        }
+                        //#If any nutrient application for any crop is not incorporated, the method score for the AoA is zero
+                        if (!crop.allNutrientsIncorporated()) {
+                            app_method_score = 0;
+                        }
+                        if (!(error_msg = crop.getErrorMsg()).isEmpty()) {
+                            break;
+                        }
+                    } else {
+                        ret_val = error_msg = "Cannot get crop_type. " + crop.getErrorMsg();
+                    }
+                }
 
-        //  If all crops' nutrients were incorporated this value will still be -1
-        if (app_method_score == -1) {
-            query = "SELECT app_mgt_score from wqm_nutrient_application_mgt_scores WHERE app_mgt_kind='Method' AND app_mgt_factor='incorporate';";
-          try(ResultSet  resultSet = statement.executeQuery(query)){
-            if (resultSet.first()) {
-            app_method_score = resultSet.getInt("app_mgt_score");
-            }
-        }
+                //  If all crops' nutrients were incorporated this value will still be -1
+                if (app_method_score == -1) {
+                    query = "SELECT app_mgt_score FROM wqm.wqm_nutrient_application_mgt_scores "
+                            + "WHERE app_mgt_kind='Method' AND app_mgt_factor='incorporate';";
+                    try (ResultSet resultSet = statement.executeQuery(query)) {
+                        if (resultSet.first()) {
+                            app_method_score = resultSet.getInt("app_mgt_score");
+                        }
+                    }
 
-        //#Compute application management scores for nitrogen in groundwater, nitrogen in surface water, and phosphorus in surface water
-        int nleach_app_mgt_score = n_app_rate_score + n_app_timing_score + app_method_score;
-        int nsurf_app_mgt_score = n_app_rate_score + n_app_timing_score + app_method_score;
-        int psurf_app_mgt_score = p_app_rate_score + p_app_timing_score + app_method_score;
-        result.add(new Result(AoAId, nleach_app_mgt_score, nsurf_app_mgt_score, psurf_app_mgt_score, n_app_rate_score, n_app_timing_score, p_app_rate_score, p_app_timing_score, app_method_score));
+                    //#Compute application management scores for nitrogen in groundwater, nitrogen in surface water, and phosphorus in surface water
+                    int nleach_app_mgt_score = n_app_rate_score + n_app_timing_score + app_method_score;
+                    int nsurf_app_mgt_score = n_app_rate_score + n_app_timing_score + app_method_score;
+                    int psurf_app_mgt_score = p_app_rate_score + p_app_timing_score + app_method_score;
+                    result.add(new Result(AoAId, nleach_app_mgt_score, nsurf_app_mgt_score, psurf_app_mgt_score, n_app_rate_score, n_app_timing_score, p_app_rate_score, p_app_timing_score, app_method_score));
                 }
-        } catch (SQLException se) {
-        throw new ServiceException("SQLException",se);
-        } catch (Exception ex) {
-        throw new ServiceException("Exception",ex);
-        }
-    }
-    
+            } catch (ServiceException | SQLException ex) {
+                LOG.log(Level.SEVERE, "SQL problem for WQM-16!", ex);
+                throw new ServiceException("SQL problem", ex);
+            } catch (Exception ex) {
+                LOG.log(Level.SEVERE, "Error in processing for WQM-16!", ex);
+                throw new ServiceException("Exception", ex);
+            }
+        }
+
     }
 
     @Override
     //writing the results back to JSON
     protected void postProcess() throws Exception {
-    for (Result rs1 : result) {
-        JSONArray tmpArr = new JSONArray();
-        tmpArr.put(JSONUtils.dataDesc("AoAId", rs1.getAoAId(), "Area of Analysis Identifier"));
-        tmpArr.put(JSONUtils.dataDesc("nleach_app_mgt_score", rs1.getNleachAppMgtScore(), "Nitrogen Application Management Score for Mitigating Leaching Loss Potential"));
-        tmpArr.put(JSONUtils.dataDesc("nsurf_app_mgt_score", rs1.getNsurfAppMgtScore(), "Nitrogen Application Management Score for Mitigating Surface Runoff Loss Potential"));
-        tmpArr.put(JSONUtils.dataDesc("psurf_app_mgt_score", rs1.getPsurfAppMgtScore(), "Phosphorus Application Management Score for Mitigating Surface Runoff Loss Potential"));
-        tmpArr.put(JSONUtils.dataDesc("n_app_rate_score", rs1.getnAppRateScore(), "Nitrogen Application Rate Mitigation Score"));
-        tmpArr.put(JSONUtils.dataDesc("n_app_timing_score", rs1.getnAppTimingScore(), "Nitrogen Application Timing Mitigation Score"));
-        tmpArr.put(JSONUtils.dataDesc("p_app_rate_score", rs1.getpAppRateScore(), "Phosphorus Application Rate Mitigation Score"));
-        tmpArr.put(JSONUtils.dataDesc("p_app_timing_score", rs1.getpAppTimingScore(), "Phosphorus Application Timing Mitigation Score"));
-        tmpArr.put(JSONUtils.dataDesc("app_method_score", rs1.getAppMethodScore(), "Nutrient Application Method Mitigation Score"));
-        putResult("Nutrition Application Summary", tmpArr, "Nutrition Application Summary");
-    }
+        try {
+            for (Result rs1 : result) {
+                JSONArray tmpArr = new JSONArray();
+                tmpArr.put(JSONUtils.dataDesc("AoAId", rs1.getAoAId(), "Area of Analysis Identifier"));
+                tmpArr.put(JSONUtils.dataDesc("nleach_app_mgt_score", rs1.getNleachAppMgtScore(), "Nitrogen Application Management Score for Mitigating Leaching Loss Potential"));
+                tmpArr.put(JSONUtils.dataDesc("nsurf_app_mgt_score", rs1.getNsurfAppMgtScore(), "Nitrogen Application Management Score for Mitigating Surface Runoff Loss Potential"));
+                tmpArr.put(JSONUtils.dataDesc("psurf_app_mgt_score", rs1.getPsurfAppMgtScore(), "Phosphorus Application Management Score for Mitigating Surface Runoff Loss Potential"));
+                tmpArr.put(JSONUtils.dataDesc("n_app_rate_score", rs1.getnAppRateScore(), "Nitrogen Application Rate Mitigation Score"));
+                tmpArr.put(JSONUtils.dataDesc("n_app_timing_score", rs1.getnAppTimingScore(), "Nitrogen Application Timing Mitigation Score"));
+                tmpArr.put(JSONUtils.dataDesc("p_app_rate_score", rs1.getpAppRateScore(), "Phosphorus Application Rate Mitigation Score"));
+                tmpArr.put(JSONUtils.dataDesc("p_app_timing_score", rs1.getpAppTimingScore(), "Phosphorus Application Timing Mitigation Score"));
+                tmpArr.put(JSONUtils.dataDesc("app_method_score", rs1.getAppMethodScore(), "Nutrient Application Method Mitigation Score"));
+                putResult("Nutrition Application Summary", tmpArr, "Nutrition Application Summary");
+            }
+        } catch (JSONException ex) {
+            LOG.log(Level.SEVERE, "Error in processing the response JSON for WQM-16!", ex);
+            throw new ServiceException("Error in processing the response JSON.", ex);
+        }
     }
 
     private boolean ValidateInput() {
-    for (Crop tCrop : cropList) {
-        if (!tCrop.validate()) {
-        error_msg += "; " + tCrop.getErrorMsg();
-        }
-    }
+        for (Crop tCrop : cropList) {
+            if (!tCrop.validate()) {
+                error_msg += "; " + tCrop.getErrorMsg();
+            }
+        }
 
-    return (error_msg.isEmpty());
+        return (error_msg.isEmpty());
     }
 
     public class Crop {
 
-    //  Begin Crop Class
-    public static final int N_APP_RATE_SCORE = 0;
-    public static final int P_APP_RATE_SCORE = 1;
-    public static final int N_APP_TIMING_SCORE = 0;
-    public static final int P_APP_TIMING_SCORE = 1;
+        //  Begin Crop Class
+        public static final int N_APP_RATE_SCORE = 0;
+        public static final int P_APP_RATE_SCORE = 1;
+        public static final int N_APP_TIMING_SCORE = 0;
+        public static final int P_APP_TIMING_SCORE = 1;
 
-    private int mgtCropId;
-    private String cropPlantDate;
-    private Date plantDate;
-    private double cropYield;
-    private String cropYieldUnits;
-    private ArrayList<Crop.NutrientApplication> nutrientApplicationList;
-    private Result calc_result;
-    private String cropType = "";
-    private String error_msg = "";
-    private Boolean multipleNutrientApplication = false;
-    private int n_app_timing_score = 100;
-    private int p_app_timing_score = 100;
-    private int app_method_score = 0;
-    private int[] appRateScore = new int[2];
-    private int[] appNutrientTimingScore = new int[2];
-    private String pSoilTestResult = "None";
+        private int mgtCropId;
+        private String cropPlantDate;
+        private Date plantDate;
+        private double cropYield;
+        private String cropYieldUnits;
+        private ArrayList<Crop.NutrientApplication> nutrientApplicationList;
+        private Result calc_result;
+        private String cropType = "";
+        private String error_msg = "";
+        private Boolean multipleNutrientApplication = false;
+        private int n_app_timing_score = 100;
+        private int p_app_timing_score = 100;
+        private int app_method_score = 0;
+        private int[] appRateScore = new int[2];
+        private int[] appNutrientTimingScore = new int[2];
+        private String pSoilTestResult = "None";
 
-    public Crop(int mgtCropId, String cropPlantDate, double cropYield,
-        String cropYieldUnits, JSONArray applicationList, String pSoilTestResult) throws ServiceException {
-        this.mgtCropId = mgtCropId;
-        this.cropPlantDate = cropPlantDate;
-        this.cropYield = cropYield;
-        this.cropYieldUnits = cropYieldUnits;
-        this.pSoilTestResult = pSoilTestResult;
+        public Crop(int mgtCropId, String cropPlantDate, double cropYield,
+                String cropYieldUnits, JSONArray applicationList, String pSoilTestResult) throws ServiceException {
+            this.mgtCropId = mgtCropId;
+            this.cropPlantDate = cropPlantDate;
+            this.cropYield = cropYield;
+            this.cropYieldUnits = cropYieldUnits;
+            this.pSoilTestResult = pSoilTestResult;
 
-        nutrientApplicationList = new ArrayList<Crop.NutrientApplication>();
+            nutrientApplicationList = new ArrayList<Crop.NutrientApplication>();
 
-        try {
-        plantDate = getCropPlantDate();
-        if (null != applicationList) {
-            for (int j = 0; j < applicationList.length(); j++) {
-            Map<String, JSONObject> application = JSONUtils.preprocess(applicationList.getJSONArray(j));
-            nutrientApplicationList.add(new Crop.NutrientApplication(JSONUtils.getStringParam(application, "nutrient_application_date", "err"), JSONUtils.getStringParam(application, "incorporated", ""), JSONUtils.getJSONArrayParam(application, "application")));
-            }
-        }
-        } catch (Exception ex) {
-            throw new ServiceException("Exception",ex);
-        }
-
-        multipleNutrientApplication = (nutrientApplicationList.size() > 1);
-        appRateScore[N_APP_RATE_SCORE] = appRateScore[P_APP_RATE_SCORE] = -1;
-        appNutrientTimingScore[N_APP_TIMING_SCORE] = appNutrientTimingScore[P_APP_TIMING_SCORE] = -1;
-    }
-
-    //Get methods
-    public int getMgtCropId() {
-        return mgtCropId;
-    }
-
-    public String getErrorMsg() {
-        for (Crop.NutrientApplication nutrientApplied : nutrientApplicationList) {
-        error_msg += nutrientApplied.getErrorMsg();
-        }
-        return error_msg;
-    }
-
-    public String getCropType() throws ServiceException {
-        if ((cropType.isEmpty()) && (error_msg.isEmpty())) {
-        
-        String query = "SELECT wqm_crop_type FROM wqm_crops WHERE wqm_crop_id=" + mgtCropId + " AND wqm_crop_units='" + cropYieldUnits + "';";
-        try (Connection conn = getResourceJDBC(WQM_ID);
-                Statement statement = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY)) {
-        try( ResultSet  resultSet = statement.executeQuery(query)){
-            if (!resultSet.first()) {
-            error_msg += "That crop, " + mgtCropId + ", and crop yield units, " + cropYieldUnits + ", was not found in the database";
-            } else {
-            cropType = resultSet.getString("wqm_crop_type");
-            }
+            try {
+                plantDate = getCropPlantDate();
+                if (null != applicationList) {
+                    for (int j = 0; j < applicationList.length(); j++) {
+                        Map<String, JSONObject> application = JSONUtils.preprocess(applicationList.getJSONArray(j));
+                        nutrientApplicationList.add(new Crop.NutrientApplication(JSONUtils.getStringParam(application, "nutrient_application_date", "err"), JSONUtils.getStringParam(application, "incorporated", ""), JSONUtils.getJSONArrayParam(application, "application")));
+                    }
                 }
-        } catch (SQLException ex) {
-                    throw new ServiceException("SQLException",ex);
-        }
-        }
-        return cropType;
-    }
-
-    public final Date getCropPlantDate() throws Exception {
-        String[] parse = cropPlantDate.split("-");
-        Calendar date = new GregorianCalendar(Integer.parseInt(parse[0]),
-            Integer.parseInt(parse[1]) - 1, Integer.parseInt(parse[2]));
-        return date.getTime();
-    }
-
-    public double getCropYield() {
-        return cropYield;
-    }
-
-    public String getCropYieldUnits() {
-        return cropYieldUnits;
-    }
-
-    public ArrayList getNutrientApplicationList() {
-        return nutrientApplicationList;
-    }
-
-    public int[] getNutrientApplicationRateScores() {
-        if ((appRateScore[N_APP_RATE_SCORE] < 0) || (appRateScore[P_APP_RATE_SCORE] < 0)) {
-        try (Connection conn = getResourceJDBC(WQM_ID);
-                Statement statement = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY)) {
-            if (nutrientApplicationList.isEmpty()) {
-            ResultSet resultSet;
-
-            appRateScore[N_APP_RATE_SCORE] = appRateScore[P_APP_RATE_SCORE] = 0;
-            String queryNitrogen = "SELECT app_mgt_score FROM wqm_nutrient_application_mgt_scores WHERE nutrient='Nitrogen' AND app_mgt_kind='Rate' AND app_mgt_factor='none';";
-            String queryPhosporous = "SELECT app_mgt_score FROM wqm_nutrient_application_mgt_scores WHERE nutrient='Phosphorus' AND app_mgt_kind='Rate' AND app_mgt_factor='none' AND soil_test_result='" + pSoilTestResult + "';";
-
-            resultSet = statement.executeQuery(queryNitrogen);
-            if (resultSet.first()) {
-                appRateScore[N_APP_RATE_SCORE] = resultSet.getInt("app_mgt_score");
-            }
-
-            resultSet = statement.executeQuery(queryPhosporous);
-            if (resultSet.first()) {
-                appRateScore[P_APP_RATE_SCORE] = resultSet.getInt("app_mgt_score");
-            }
-            } else {
-            ResultSet resultSet;
-            String query;
-
-            double nrate = 0.0;
-            double prate = 0.0;
-
-            double wqm_crop_pct_dmat = 0.0;
-            double wqm_pct_nitrogen = 0.0;
-            double wqm_pct_phosphorus = 0.0;
-            double wqm_crop_yield = 0.0;
-
-            int ncrop_app_rate_score = 0;
-            int pcrop_app_rate_score = 0;
-
-            for (Crop.NutrientApplication nutrient : nutrientApplicationList) {
-                ArrayList<Crop.NutrientApplication.Nutrient> nutrientAppliedList = nutrient.getNutrientList();
-                for (Crop.NutrientApplication.Nutrient nApplied : nutrientAppliedList) {
-                switch (nApplied.getNutrientApplied()) {  //Note:  This switch requires JDK 1.7 or above
-                    case "Nitrogen":
-                    nrate += nApplied.getApplicationRate();
-                    break;
-                    case "Phosphorus":
-                    prate += nApplied.getApplicationRate();
-                    break;
-                }
-                }
-            }
-
-            query = "SELECT wqm_crop_pct_dmat, wqm_pct_nitrogen, wqm_pct_phosphorus, wqm_crop_yield FROM wqm_crops WHERE wqm_crop_id=" + mgtCropId + ";";
-            resultSet = statement.executeQuery(query);
-            if (resultSet.first()) {
-                wqm_crop_pct_dmat = resultSet.getDouble("wqm_crop_pct_dmat");
-                wqm_pct_nitrogen = resultSet.getDouble("wqm_pct_nitrogen");
-                wqm_pct_phosphorus = resultSet.getDouble("wqm_pct_phosphorus");
-                wqm_crop_yield = resultSet.getDouble("wqm_crop_yield");
-
-                //  Added wqm_crop_yield to the calc per bug #462839
-                double n_growout = cropYield * wqm_crop_yield * wqm_crop_pct_dmat * wqm_pct_nitrogen;
-                double p_growout = cropYield * wqm_crop_yield * wqm_crop_pct_dmat * wqm_pct_phosphorus;
-
-                double n_remove_ratio = nrate / n_growout;
-                double p_remove_ratio = prate / p_growout;
-
-                query = "SELECT app_mgt_score FROM wqm_nutrient_application_mgt_scores WHERE nutrient='" + "Nitrogen" + "' AND app_mgt_kind='" + "Rate" + "' AND app_mgt_factor=";
-
-                switch (cropType) {
-                case "Small Grain":  //Note the case conflicts here...
-                    query += "'small grain'";
-                    break;
-
-                default:
-                    query += "'other'";
-                }
-                query += " AND remove_ratio_1 <= " + n_remove_ratio + "AND remove_ratio_2 > " + n_remove_ratio + ";";
-
-                resultSet = statement.executeQuery(query);
-                if (resultSet.first()) {
-                ncrop_app_rate_score = resultSet.getInt("app_mgt_score");
-                } else {
-                appRateScore[N_APP_RATE_SCORE] = appRateScore[P_APP_RATE_SCORE] = 0;
-                }
-
-                pcrop_app_rate_score = -1;
-                //#Compute P application management rate scores based on removal ratio and soil test result
-                switch (pSoilTestResult) {
-                case "High":
-                    if (p_remove_ratio >= 1.2) {
-                    pcrop_app_rate_score = 0;
-                    }
-                    break;
-                case "Medium":
-                case "Low":
-                    if (p_remove_ratio >= 1.6) {
-                    pcrop_app_rate_score = 0;
-                    }
-                    break;
-                case "None":
-                    if (p_remove_ratio >= 1.2) {
-                    pcrop_app_rate_score = 0;
-                    }
-                    break;
-                }
-
-                if (pcrop_app_rate_score == -1) {
-                query = "SELECT app_mgt_score FROM wqm_nutrient_application_mgt_scores WHERE nutrient='Phosphorus' AND app_mgt_kind='Rate' AND app_mgt_factor='app' AND soil_test_result='" + pSoilTestResult + "' AND remove_ratio_1 <= " + p_remove_ratio + " AND remove_ratio_2 > " + p_remove_ratio + ";";
-                resultSet = statement.executeQuery(query);
-                if (resultSet.first()) {
-                    pcrop_app_rate_score = resultSet.getInt("app_mgt_score");
-                }
-                }
-
-                if (pcrop_app_rate_score != -1) {
-                //#Update N and P application management rate scores for the AoA
-                appRateScore[N_APP_RATE_SCORE] = ncrop_app_rate_score;
-                appRateScore[P_APP_RATE_SCORE] = pcrop_app_rate_score;
-                } else {//We have a problem...no validity in any following computations if we proceed since the last query failed to find any data.  What would you like to do?
-                appRateScore[N_APP_RATE_SCORE] = appRateScore[P_APP_RATE_SCORE] = 0;
-                }
-            } else { //We have a problem...no validity in any following computations if we proceed.  What would you like to do?
-                appRateScore[N_APP_RATE_SCORE] = appRateScore[P_APP_RATE_SCORE] = 0;
-            }
-            }
-        } catch (SQLException ex) {
-            error_msg += ex.getMessage();
-        } catch (ServiceException ex) {
-            Logger.getLogger(V1_0.class.getName()).log(Level.SEVERE, null, ex);
-        }
+            } catch (Exception ex) {
+                LOG.log(Level.SEVERE, "Error in processing for WQM-16!", ex);
+                throw new ServiceException("Exception", ex);
             }
 
-        return appRateScore;
-    }
+            multipleNutrientApplication = (nutrientApplicationList.size() > 1);
+            appRateScore[N_APP_RATE_SCORE] = appRateScore[P_APP_RATE_SCORE] = -1;
+            appNutrientTimingScore[N_APP_TIMING_SCORE] = appNutrientTimingScore[P_APP_TIMING_SCORE] = -1;
+        }
 
-    public int[] getNutrientApplicationTimingScores() throws ServiceException {
-        if ((appNutrientTimingScore[N_APP_TIMING_SCORE] < 0) || (appNutrientTimingScore[P_APP_TIMING_SCORE] < 0)) {
-        int tempNScore = 100;
-        int tempPScore = 100;
+        //Get methods
+        public int getMgtCropId() {
+            return mgtCropId;
+        }
 
-        for (Crop.NutrientApplication nutrientApplication : nutrientApplicationList) {
-            //  Call each application compare its results to the last and adjust main score if necessary.
-            int[] tempAppTimingScores = nutrientApplication.getNutrientTimingScores(multipleNutrientApplication);
+        public String getErrorMsg() {
+            for (Crop.NutrientApplication nutrientApplied : nutrientApplicationList) {
+                error_msg += nutrientApplied.getErrorMsg();
+            }
+            return error_msg;
+        }
 
-            if (tempAppTimingScores[N_APP_TIMING_SCORE] < tempNScore) {
-            tempNScore = tempAppTimingScores[N_APP_TIMING_SCORE];
-            }
+        public String getCropType() throws ServiceException {
+            if ((cropType.isEmpty()) && (error_msg.isEmpty())) {
 
-            if (tempAppTimingScores[P_APP_TIMING_SCORE] < tempPScore) {
-            tempPScore = tempAppTimingScores[P_APP_TIMING_SCORE];
-            }
-        }
+                String query = "SELECT wqm_crop_type FROM wqm.wqm_crops WHERE wqm_crop_id="
+                        + mgtCropId + " AND wqm_crop_units='" + cropYieldUnits + "';";
+                try (Connection conn = getResourceJDBC(WQM_ID);
+                        Statement statement = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY)) {
+                    try (ResultSet resultSet = statement.executeQuery(query)) {
+                        if (!resultSet.first()) {
+                            error_msg += "That crop, " + mgtCropId + ", and crop yield units, " + cropYieldUnits + ", was not found in the database";
+                        } else {
+                            cropType = resultSet.getString("wqm_crop_type");
+                        }
+                    }
+                } catch (ServiceException | SQLException ex) {
+                    LOG.log(Level.SEVERE, "SQL problem for WQM-16!", ex);
+                    throw new ServiceException("SQL problem", ex);
+                }
+            }
+            return cropType;
+        }
 
-        appNutrientTimingScore[P_APP_TIMING_SCORE] = tempPScore;
-        appNutrientTimingScore[N_APP_TIMING_SCORE] = tempNScore;
-        }
+        public final Date getCropPlantDate() throws Exception {
+            String[] parse = cropPlantDate.split("-");
+            Calendar date = new GregorianCalendar(Integer.parseInt(parse[0]),
+                    Integer.parseInt(parse[1]) - 1, Integer.parseInt(parse[2]));
+            return date.getTime();
+        }
 
-        return appNutrientTimingScore;
-    }
+        public double getCropYield() {
+            return cropYield;
+        }
 
-    public Boolean allNutrientsIncorporated() {
-        Boolean ret_val = true;
-        for (Crop.NutrientApplication nutrientApplication : nutrientApplicationList) {
-        if (!nutrientApplication.allNutrientsIncorporated()) {
-            ret_val = false;
-            break;
-        }
-        }
+        public String getCropYieldUnits() {
+            return cropYieldUnits;
+        }
 
-        return ret_val;
-    }
+        public ArrayList getNutrientApplicationList() {
+            return nutrientApplicationList;
+        }
 
-    public String processCropData() {
-        String ret_val = "";
+        public int[] getNutrientApplicationRateScores() throws ServiceException {
+            if ((appRateScore[N_APP_RATE_SCORE] < 0) || (appRateScore[P_APP_RATE_SCORE] < 0)) {
+                try (Connection conn = getResourceJDBC(WQM_ID);
+                        Statement statement = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY)) {
+                    if (nutrientApplicationList.isEmpty()) {
+                        ResultSet resultSet;
 
-        return ret_val;
-    }
+                        appRateScore[N_APP_RATE_SCORE] = appRateScore[P_APP_RATE_SCORE] = 0;
+                        String queryNitrogen = "SELECT app_mgt_score "
+                                + "FROM wqm.wqm_nutrient_application_mgt_scores "
+                                + "WHERE nutrient='Nitrogen' AND app_mgt_kind='Rate' AND app_mgt_factor='none';";
+                        String queryPhosporous = "SELECT app_mgt_score "
+                                + "FROM wqm.wqm_nutrient_application_mgt_scores "
+                                + "WHERE nutrient='Phosphorus' AND app_mgt_kind='Rate' "
+                                + "AND app_mgt_factor='none' AND soil_test_result='" + pSoilTestResult + "';";
 
-    public Boolean validate() {
-        for (Crop.NutrientApplication tNutrientApplication : nutrientApplicationList) {
-        if (!tNutrientApplication.validate()) {
-            error_msg += "; " + tNutrientApplication.getErrorMsg();
-        }
-        }
+                        resultSet = statement.executeQuery(queryNitrogen);
+                        if (resultSet.first()) {
+                            appRateScore[N_APP_RATE_SCORE] = resultSet.getInt("app_mgt_score");
+                        }
 
-        return (error_msg.isEmpty());
-    }
+                        resultSet = statement.executeQuery(queryPhosporous);
+                        if (resultSet.first()) {
+                            appRateScore[P_APP_RATE_SCORE] = resultSet.getInt("app_mgt_score");
+                        }
+                    } else {
+                        ResultSet resultSet;
+                        String query;
 
-    //  Inner Classes
-    class NutrientApplication {
+                        double nrate = 0.0;
+                        double prate = 0.0;
 
-        class Nutrient {
+                        double wqm_crop_pct_dmat = 0.0;
+                        double wqm_pct_nitrogen = 0.0;
+                        double wqm_pct_phosphorus = 0.0;
+                        double wqm_crop_yield = 0.0;
 
-        private final String nutrientApplied;
-        private final double applicationRate;
+                        int ncrop_app_rate_score = 0;
+                        int pcrop_app_rate_score = 0;
 
-        Nutrient(String nutrientApplied, double applicationRate) throws ServiceException {
-            this.nutrientApplied = nutrientApplied;
-            this.applicationRate = applicationRate;
+                        for (Crop.NutrientApplication nutrient : nutrientApplicationList) {
+                            ArrayList<Crop.NutrientApplication.Nutrient> nutrientAppliedList = nutrient.getNutrientList();
+                            for (Crop.NutrientApplication.Nutrient nApplied : nutrientAppliedList) {
+                                switch (nApplied.getNutrientApplied()) {  //Note:  This switch requires JDK 1.7 or above
+                                    case "Nitrogen":
+                                        nrate += nApplied.getApplicationRate();
+                                        break;
+                                    case "Phosphorus":
+                                        prate += nApplied.getApplicationRate();
+                                        break;
+                                }
+                            }
+                        }
 
-            if (!nutrientApplied.equals("Nitrogen") && !nutrientApplied.equals("Phosphorus")) {
-              throw new ServiceException("Invalid input data.  Bad nutrient name");
-            }
-        }
+                        query = "SELECT wqm_crop_pct_dmat, wqm_pct_nitrogen, wqm_pct_phosphorus, wqm_crop_yield "
+                                + "FROM wqm.wqm_crops WHERE wqm_crop_id=" + mgtCropId + ";";
+                        resultSet = statement.executeQuery(query);
+                        if (resultSet.first()) {
+                            wqm_crop_pct_dmat = resultSet.getDouble("wqm_crop_pct_dmat");
+                            wqm_pct_nitrogen = resultSet.getDouble("wqm_pct_nitrogen");
+                            wqm_pct_phosphorus = resultSet.getDouble("wqm_pct_phosphorus");
+                            wqm_crop_yield = resultSet.getDouble("wqm_crop_yield");
 
-        //Get Methods
-        public String getNutrientApplied() {
-            return nutrientApplied;
-        }
+                            //  Added wqm_crop_yield to the calc per bug #462839
+                            double n_growout = cropYield * wqm_crop_yield * wqm_crop_pct_dmat * wqm_pct_nitrogen;
+                            double p_growout = cropYield * wqm_crop_yield * wqm_crop_pct_dmat * wqm_pct_phosphorus;
 
-        public double getApplicationRate() {
-            return applicationRate;
-        }
+                            double n_remove_ratio = nrate / n_growout;
+                            double p_remove_ratio = prate / p_growout;
 
-        public String getErrorMsg() {
-            return error_msg;
-        }
+                            query = "SELECT app_mgt_score FROM wqm.wqm_nutrient_application_mgt_scores "
+                                    + "WHERE nutrient = 'Nitrogen' AND app_mgt_kind = 'Rate' AND app_mgt_factor=";
 
-        public Boolean validate() {
-            return (error_msg.isEmpty());
-        }
-        }
-        private String error_msg = "";
-        private String applicationDate;
-        private boolean incorporated;
-        private ArrayList<Crop.NutrientApplication.Nutrient> nutrientList;
-        private int appMethodScore = 0;
-        private int[] nutrientTimingScores = new int[2];
+                            switch (cropType) {
+                                case "Small Grain":  //Note the case conflicts here...
+                                    query += "'small grain'";
+                                    break;
 
-        NutrientApplication(String applicationDate, String incorporated, JSONArray applications) throws ServiceException {
-        this.applicationDate = applicationDate;
-        nutrientTimingScores[N_APP_TIMING_SCORE] = nutrientTimingScores[P_APP_TIMING_SCORE] = -1;
-        if ((!"true".equalsIgnoreCase(incorporated)) && (!"false".equalsIgnoreCase(incorporated))) {
-        throw new ServiceException("Invalid incorporation value for nutrient application " + applicationDate);
+                                default:
+                                    query += "'other'";
+                            }
+                            query += " AND remove_ratio_1 <= " + n_remove_ratio + "AND remove_ratio_2 > " + n_remove_ratio + ";";
+
+                            resultSet = statement.executeQuery(query);
+                            if (resultSet.first()) {
+                                ncrop_app_rate_score = resultSet.getInt("app_mgt_score");
+                            } else {
+                                appRateScore[N_APP_RATE_SCORE] = appRateScore[P_APP_RATE_SCORE] = 0;
+                            }
+
+                            pcrop_app_rate_score = -1;
+                            //#Compute P application management rate scores based on removal ratio and soil test result
+                            switch (pSoilTestResult) {
+                                case "High":
+                                    if (p_remove_ratio >= 1.2) {
+                                        pcrop_app_rate_score = 0;
+                                    }
+                                    break;
+                                case "Medium":
+                                case "Low":
+                                    if (p_remove_ratio >= 1.6) {
+                                        pcrop_app_rate_score = 0;
+                                    }
+                                    break;
+                                case "None":
+                                    if (p_remove_ratio >= 1.2) {
+                                        pcrop_app_rate_score = 0;
+                                    }
+                                    break;
+                            }
+
+                            if (pcrop_app_rate_score == -1) {
+                                query = "SELECT app_mgt_score FROM wqm.wqm_nutrient_application_mgt_scores "
+                                        + "WHERE nutrient='Phosphorus' AND app_mgt_kind='Rate' "
+                                        + "AND app_mgt_factor='app' AND soil_test_result='"
+                                        + pSoilTestResult + "' AND remove_ratio_1 <= " + p_remove_ratio
+                                        + " AND remove_ratio_2 > " + p_remove_ratio + ";";
+                                resultSet = statement.executeQuery(query);
+                                if (resultSet.first()) {
+                                    pcrop_app_rate_score = resultSet.getInt("app_mgt_score");
+                                }
+                            }
+
+                            if (pcrop_app_rate_score != -1) {
+                                //#Update N and P application management rate scores for the AoA
+                                appRateScore[N_APP_RATE_SCORE] = ncrop_app_rate_score;
+                                appRateScore[P_APP_RATE_SCORE] = pcrop_app_rate_score;
+                            } else {//We have a problem...no validity in any following computations if we proceed since the last query failed to find any data.  What would you like to do?
+                                appRateScore[N_APP_RATE_SCORE] = appRateScore[P_APP_RATE_SCORE] = 0;
+                            }
+                        } else { //We have a problem...no validity in any following computations if we proceed.  What would you like to do?
+                            appRateScore[N_APP_RATE_SCORE] = appRateScore[P_APP_RATE_SCORE] = 0;
+                        }
+                    }
+                } catch (ServiceException | SQLException ex) {
+                    error_msg += ex.getMessage();
+                    LOG.log(Level.SEVERE, "SQL problem for WQM-16!", ex);
+                    throw new ServiceException("SQL problem", ex);
+                }
+            }
+
+            return appRateScore;
+        }
+
+        public int[] getNutrientApplicationTimingScores() throws ServiceException, Exception {
+            if ((appNutrientTimingScore[N_APP_TIMING_SCORE] < 0) || (appNutrientTimingScore[P_APP_TIMING_SCORE] < 0)) {
+                int tempNScore = 100;
+                int tempPScore = 100;
+
+                for (Crop.NutrientApplication nutrientApplication : nutrientApplicationList) {
+                    //  Call each application compare its results to the last and adjust main score if necessary.
+                    int[] tempAppTimingScores = nutrientApplication.getNutrientTimingScores(multipleNutrientApplication);
+
+                    if (tempAppTimingScores[N_APP_TIMING_SCORE] < tempNScore) {
+                        tempNScore = tempAppTimingScores[N_APP_TIMING_SCORE];
+                    }
+
+                    if (tempAppTimingScores[P_APP_TIMING_SCORE] < tempPScore) {
+                        tempPScore = tempAppTimingScores[P_APP_TIMING_SCORE];
+                    }
+                }
+
+                appNutrientTimingScore[P_APP_TIMING_SCORE] = tempPScore;
+                appNutrientTimingScore[N_APP_TIMING_SCORE] = tempNScore;
+            }
+
+            return appNutrientTimingScore;
+        }
+
+        public Boolean allNutrientsIncorporated() {
+            Boolean ret_val = true;
+            for (Crop.NutrientApplication nutrientApplication : nutrientApplicationList) {
+                if (!nutrientApplication.allNutrientsIncorporated()) {
+                    ret_val = false;
+                    break;
+                }
+            }
+
+            return ret_val;
+        }
+
+        public String processCropData() {
+            String ret_val = "";
+
+            return ret_val;
+        }
+
+        public Boolean validate() {
+            for (Crop.NutrientApplication tNutrientApplication : nutrientApplicationList) {
+                if (!tNutrientApplication.validate()) {
+                    error_msg += "; " + tNutrientApplication.getErrorMsg();
+                }
+            }
+
+            return (error_msg.isEmpty());
+        }
+
+        //  Inner Classes
+        class NutrientApplication {
+
+            class Nutrient {
+
+                private final String nutrientApplied;
+                private final double applicationRate;
+
+                Nutrient(String nutrientApplied, double applicationRate) throws ServiceException {
+                    this.nutrientApplied = nutrientApplied;
+                    this.applicationRate = applicationRate;
+
+                    if (!nutrientApplied.equals("Nitrogen") && !nutrientApplied.equals("Phosphorus")) {
+                        throw new ServiceException("Invalid input data.  Bad nutrient name");
+                    }
+                }
+
+                //Get Methods
+                public String getNutrientApplied() {
+                    return nutrientApplied;
+                }
+
+                public double getApplicationRate() {
+                    return applicationRate;
+                }
+
+                public String getErrorMsg() {
+                    return error_msg;
+                }
+
+                public Boolean validate() {
+                    return (error_msg.isEmpty());
+                }
+            }
+            private String error_msg = "";
+            private String applicationDate;
+            private boolean incorporated;
+            private ArrayList<Crop.NutrientApplication.Nutrient> nutrientList;
+            private int appMethodScore = 0;
+            private int[] nutrientTimingScores = new int[2];
+
+            NutrientApplication(String applicationDate, String incorporated, JSONArray applications) throws ServiceException {
+                this.applicationDate = applicationDate;
+                nutrientTimingScores[N_APP_TIMING_SCORE] = nutrientTimingScores[P_APP_TIMING_SCORE] = -1;
+                if ((!"true".equalsIgnoreCase(incorporated)) && (!"false".equalsIgnoreCase(incorporated))) {
+                    throw new ServiceException("Invalid incorporation value for nutrient application " + applicationDate);
                 } else {
-            this.incorporated = Boolean.parseBoolean(incorporated);
-            nutrientList = new ArrayList<>();
-            try {
-            for (int k = 0; k < applications.length(); k++) {
-                Map<String, JSONObject> nutrient = JSONUtils.preprocess(applications.getJSONArray(k));
-                nutrientList.add(new Crop.NutrientApplication.Nutrient(JSONUtils.getStringParam(nutrient, "nutrient_applied", "err"), JSONUtils.getDoubleParam(nutrient, "application_rate", 0)));
-            }
-            } catch (JSONException ex) {
-         throw new ServiceException("JSONException",ex);
-            }
-        }
-        }
+                    this.incorporated = Boolean.parseBoolean(incorporated);
+                    nutrientList = new ArrayList<>();
+                    try {
+                        for (int k = 0; k < applications.length(); k++) {
+                            Map<String, JSONObject> nutrient = JSONUtils.preprocess(applications.getJSONArray(k));
+                            nutrientList.add(new Crop.NutrientApplication.Nutrient(JSONUtils.getStringParam(nutrient, "nutrient_applied", "err"), JSONUtils.getDoubleParam(nutrient, "application_rate", 0)));
+                        }
+                    } catch (JSONException ex) {
+                        LOG.log(Level.SEVERE, "Error in processing for WQM-16!", ex);
+                        throw new ServiceException("JSONException", ex);
+                    }
+                }
+            }
 
-        //Get Methods
-        public Date getApplicationDate() throws Exception {
-        String[] parse = applicationDate.split("-");
-        //Some say should set to use UTC first...do we wanna do that?
-        Calendar date = new GregorianCalendar(Integer.parseInt(parse[0]),
-            Integer.parseInt(parse[1]) - 1, Integer.parseInt(parse[2]));
-        return date.getTime();
-        }
+            //Get Methods
+            public Date getApplicationDate() throws Exception {
+                String[] parse = applicationDate.split("-");
+                //Some say should set to use UTC first...do we wanna do that?
+                Calendar date = new GregorianCalendar(Integer.parseInt(parse[0]),
+                        Integer.parseInt(parse[1]) - 1, Integer.parseInt(parse[2]));
+                return date.getTime();
+            }
 
-        public boolean isIncorporated() {
-        return incorporated;
-        }
+            public boolean isIncorporated() {
+                return incorporated;
+            }
 
-        public ArrayList getNutrientList() {
-        return nutrientList;
-        }
+            public ArrayList getNutrientList() {
+                return nutrientList;
+            }
 
-        public String getErrorMsg() {
-        for (Crop.NutrientApplication.Nutrient nutrient : nutrientList) {
-            error_msg += nutrient.getErrorMsg();
-        }
-        return error_msg;
-        }
+            public String getErrorMsg() {
+                for (Crop.NutrientApplication.Nutrient nutrient : nutrientList) {
+                    error_msg += nutrient.getErrorMsg();
+                }
+                return error_msg;
+            }
 
-        public Boolean validate() {
-        for (Crop.NutrientApplication.Nutrient nutrient : nutrientList) {
-            if (!nutrient.validate()) {
-            error_msg += "; " + nutrient.getErrorMsg();
-            }
-        }
-        return (error_msg.isEmpty());
-        }
+            public Boolean validate() {
+                for (Crop.NutrientApplication.Nutrient nutrient : nutrientList) {
+                    if (!nutrient.validate()) {
+                        error_msg += "; " + nutrient.getErrorMsg();
+                    }
+                }
+                return (error_msg.isEmpty());
+            }
 
-        public int[] getNutrientTimingScores(Boolean split) throws ServiceException {
-        if ((nutrientTimingScores[N_APP_TIMING_SCORE] < 0) || (nutrientTimingScores[P_APP_TIMING_SCORE] < 0)) {
-            int tempNScore = 100;
-            int tempPScore = 100;
-           
-            for (Crop.NutrientApplication.Nutrient nutrient : nutrientList) {
-            int app_timing_score;
-            try (Connection conn = getResourceJDBC(WQM_ID);
-                Statement statement = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY)) {
-                long app_day_diff = Dates.diffInMillis(getCropPlantDate(), getApplicationDate());
-                app_day_diff = TimeUnit.MILLISECONDS.toDays(app_day_diff);
-                String query = "SELECT app_mgt_score FROM wqm_nutrient_application_mgt_scores WHERE nutrient='";
-                query += nutrient.getNutrientApplied() + "' ";
-                query += "AND app_mgt_kind='Timing' AND app_mgt_factor='" + (split ? "split" : "nosplit") + "'AND days_fr_plant_1 <= " + app_day_diff + "AND days_fr_plant_2 > " + app_day_diff + ";";
-              try( ResultSet  resultSet = statement.executeQuery(query)){
-                if (!resultSet.first()) {
-                app_timing_score = -1;
-                } else {
-                app_timing_score = resultSet.getInt("app_mgt_score");
-                }
-                switch (nutrient.getNutrientApplied()) {
-                case "Nitrogen":
-                    if (app_timing_score < tempNScore) {
-                    tempNScore = app_timing_score;
-                    }
-                    break;
-                case "Phosphorus":
-                    if (app_timing_score < tempPScore) {
-                    tempPScore = app_timing_score;
-                    }
-                    break;
-                default:
-                    error_msg += "Invalid nutrient name specified";
-                }
-                          }
-            } catch (Exception ex) {
-            throw new ServiceException("Exception",ex);
+            public int[] getNutrientTimingScores(Boolean split) throws ServiceException, Exception {
+                if ((nutrientTimingScores[N_APP_TIMING_SCORE] < 0) || (nutrientTimingScores[P_APP_TIMING_SCORE] < 0)) {
+                    int tempNScore = 100;
+                    int tempPScore = 100;
+
+                    for (Crop.NutrientApplication.Nutrient nutrient : nutrientList) {
+                        int app_timing_score;
+                        try (Connection conn = getResourceJDBC(WQM_ID);
+                                Statement statement = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY)) {
+                            long app_day_diff = Dates.diffInMillis(getCropPlantDate(), getApplicationDate());
+                            app_day_diff = TimeUnit.MILLISECONDS.toDays(app_day_diff);
+                            String query = "SELECT app_mgt_score "
+                                    + "FROM wqm.wqm_nutrient_application_mgt_scores WHERE nutrient='";
+                            query += nutrient.getNutrientApplied() + "' ";
+                            query += "AND app_mgt_kind='Timing' AND app_mgt_factor='" + (split ? "split" : "nosplit") + "'AND days_fr_plant_1 <= " + app_day_diff + "AND days_fr_plant_2 > " + app_day_diff + ";";
+                            try (ResultSet resultSet = statement.executeQuery(query)) {
+                                if (!resultSet.first()) {
+                                    app_timing_score = -1;
+                                } else {
+                                    app_timing_score = resultSet.getInt("app_mgt_score");
+                                }
+                                switch (nutrient.getNutrientApplied()) {
+                                    case "Nitrogen":
+                                        if (app_timing_score < tempNScore) {
+                                            tempNScore = app_timing_score;
+                                        }
+                                        break;
+                                    case "Phosphorus":
+                                        if (app_timing_score < tempPScore) {
+                                            tempPScore = app_timing_score;
+                                        }
+                                        break;
+                                    default:
+                                        error_msg += "Invalid nutrient name specified";
+                                }
+                            }
+                        } catch (ServiceException | SQLException ex) {
+                            LOG.log(Level.SEVERE, "SQL problem for WQM-16!", ex);
+                            throw new ServiceException("SQL problem", ex);
                         }
-            if (error_msg.isEmpty()) {
-                nutrientTimingScores[N_APP_TIMING_SCORE] = tempNScore;
-                nutrientTimingScores[P_APP_TIMING_SCORE] = tempPScore;
-            }
-            }
-        }
-        return nutrientTimingScores;
-        }
+                        if (error_msg.isEmpty()) {
+                            nutrientTimingScores[N_APP_TIMING_SCORE] = tempNScore;
+                            nutrientTimingScores[P_APP_TIMING_SCORE] = tempPScore;
+                        }
+                    }
+                }
+                return nutrientTimingScores;
+            }
 
-        public Boolean allNutrientsIncorporated() {
-        return incorporated;
-        }
-    }
+            public Boolean allNutrientsIncorporated() {
+                return incorporated;
+            }
+        }
     }
 
-    public class Result {
+    static class Result {
 
-    private int AoAId;
-    private int nleach_app_mgt_score;
-    private int nsurf_app_mgt_score;
-    private int psurf_app_mgt_score;
-    private int n_app_rate_score;
-    private int n_app_timing_score;
-    private int p_app_rate_score;
-    private int p_app_timing_score;
-    private int app_method_score;
+        int AoAId;
+        int nleach_app_mgt_score;
+        int nsurf_app_mgt_score;
+        int psurf_app_mgt_score;
+        int n_app_rate_score;
+        int n_app_timing_score;
+        int p_app_rate_score;
+        int p_app_timing_score;
+        int app_method_score;
 
-    public Result(int AoAId, int nleach_app_mgt_score, int nsurf_app_mgt_score,
-        int psurf_app_mgt_score, int n_app_rate_score, int n_app_timing_score,
-        int p_app_rate_score, int p_app_timing_score, int app_method_score) {
-        this.AoAId = AoAId;
-        this.nleach_app_mgt_score = nleach_app_mgt_score;
-        this.nsurf_app_mgt_score = nsurf_app_mgt_score;
-        this.psurf_app_mgt_score = psurf_app_mgt_score;
-        this.n_app_rate_score = n_app_rate_score;
-        this.n_app_timing_score = n_app_timing_score;
-        this.p_app_rate_score = p_app_rate_score;
-        this.p_app_timing_score = p_app_timing_score;
-        this.app_method_score = app_method_score;
-    }
+        public Result(int AoAId, int nleach_app_mgt_score, int nsurf_app_mgt_score,
+                int psurf_app_mgt_score, int n_app_rate_score, int n_app_timing_score,
+                int p_app_rate_score, int p_app_timing_score, int app_method_score) {
+            this.AoAId = AoAId;
+            this.nleach_app_mgt_score = nleach_app_mgt_score;
+            this.nsurf_app_mgt_score = nsurf_app_mgt_score;
+            this.psurf_app_mgt_score = psurf_app_mgt_score;
+            this.n_app_rate_score = n_app_rate_score;
+            this.n_app_timing_score = n_app_timing_score;
+            this.p_app_rate_score = p_app_rate_score;
+            this.p_app_timing_score = p_app_timing_score;
+            this.app_method_score = app_method_score;
+        }
 
-    //Getter Methods
-    public int getAoAId() {
-        return AoAId;
-    }
+        //Getter Methods
+        public int getAoAId() {
+            return AoAId;
+        }
 
-    public int getNleachAppMgtScore() {
-        return nleach_app_mgt_score;
-    }
+        public int getNleachAppMgtScore() {
+            return nleach_app_mgt_score;
+        }
 
-    public int getNsurfAppMgtScore() {
-        return nsurf_app_mgt_score;
-    }
+        public int getNsurfAppMgtScore() {
+            return nsurf_app_mgt_score;
+        }
 
-    public int getPsurfAppMgtScore() {
-        return psurf_app_mgt_score;
-    }
+        public int getPsurfAppMgtScore() {
+            return psurf_app_mgt_score;
+        }
 
-    public int getnAppRateScore() {
-        return n_app_rate_score;
-    }
+        public int getnAppRateScore() {
+            return n_app_rate_score;
+        }
 
-    public int getnAppTimingScore() {
-        return n_app_timing_score;
-    }
+        public int getnAppTimingScore() {
+            return n_app_timing_score;
+        }
 
-    public int getpAppRateScore() {
-        return p_app_rate_score;
-    }
+        public int getpAppRateScore() {
+            return p_app_rate_score;
+        }
 
-    public int getpAppTimingScore() {
-        return p_app_timing_score;
-    }
+        public int getpAppTimingScore() {
+            return p_app_timing_score;
+        }
 
-    public int getAppMethodScore() {
-        return app_method_score;
-    }
+        public int getAppMethodScore() {
+            return app_method_score;
+        }
     }
 
 }