Java tutorial
/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.alibaba.jstorm.ui.utils; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.text.DateFormat; import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.*; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import com.alibaba.jstorm.ui.model.graph.*; import org.apache.commons.lang.StringUtils; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpPost; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.util.EntityUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.ui.ModelMap; import org.yaml.snakeyaml.Yaml; import com.alibaba.jstorm.client.ConfigExtension; import com.alibaba.jstorm.metric.AsmWindow; import com.alibaba.jstorm.metric.MetricDef; import com.alibaba.jstorm.ui.model.ClusterConfig; import com.alibaba.jstorm.ui.model.ClusterEntity; import com.alibaba.jstorm.ui.model.Response; import com.alibaba.jstorm.utils.JStormUtils; import com.alibaba.jstorm.utils.NetWorkUtils; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import backtype.storm.Config; import backtype.storm.generated.Bolt; import backtype.storm.generated.ClusterSummary; import backtype.storm.generated.GlobalStreamId; import backtype.storm.generated.Grouping; import backtype.storm.generated.MetricInfo; import backtype.storm.generated.MetricSnapshot; import backtype.storm.generated.NimbusSummary; import backtype.storm.generated.SpoutSpec; import backtype.storm.generated.StormTopology; import backtype.storm.utils.NimbusClient; import backtype.storm.utils.Utils; /** * @author Jark (wuchong.wc@alibaba-inc.com) */ public class UIUtils { private static final Logger LOG = LoggerFactory.getLogger(UIUtils.class); public static Map<String, ClusterConfig> clusterConfig = new HashMap<>(); public static Map<String, ClusterEntity> clustersCache = new HashMap<>(); public static Map uiConfig = null; public static boolean isInitialized = false; private static long uiConfigLastModified = 0; private static String confPath = System.getProperty("user.home") + File.separator + ".jstorm" + File.separator + "storm.yaml"; private static DateFormat dayFormat = new SimpleDateFormat("MM-dd HH:mm"); private static DateFormat dateFormat = new SimpleDateFormat("YYYY-MM-dd HH:mm"); private static ScheduledExecutorService poolThread = Executors.newScheduledThreadPool(1); static { readUiConfig(); //refresh the cluster cache every 3 minutes poolThread.scheduleAtFixedRate(new Runnable() { @Override public void run() { flushClusterCache(); LOG.info("refresh the cluster cache, total active cluster:{}", NimbusClientManager.getClientSize()); } }, 3, 3, TimeUnit.MINUTES); } public static Map readUiConfig() { File file = new File(confPath); //check whether ui config is update, if not , skip reload config if (!isFileModified(file)) { return uiConfig; } // reload config Map ret = Utils.readStormConfig(); ret.remove(Config.STORM_ZOOKEEPER_ROOT); ret.remove(Config.STORM_ZOOKEEPER_SERVERS); ret.remove("cluster.name"); if (file.exists()) { FileInputStream fileStream; try { fileStream = new FileInputStream(file); Yaml yaml = new Yaml(); Map clientConf = (Map) yaml.load(fileStream); if (clientConf != null) { ret.putAll(clientConf); } } catch (FileNotFoundException e) { } if (!ret.containsKey(Config.NIMBUS_HOST)) { ret.put(Config.NIMBUS_HOST, "localhost"); } uiConfig = ret; isInitialized = false; //flush cluster config flushClusterConfig(); //flush cluster cache flushClusterCache(); } return uiConfig; } private static boolean isFileModified(File file) { long lastModified = file.lastModified(); if (uiConfigLastModified == 0 || uiConfigLastModified < lastModified) { uiConfigLastModified = lastModified; return true; } else { return false; } } private static void flushClusterCache() { NimbusClient client = null; Map<String, ClusterEntity> clusterEntities = new HashMap<>(); for (String name : UIUtils.clusterConfig.keySet()) { try { client = NimbusClientManager.getNimbusClient(name); int port = getNimbusPort(name); clusterEntities.put(name, getClusterEntity(client.getClient().getClusterInfo(), name, port)); } catch (Exception e) { NimbusClientManager.removeClient(name); LOG.error(e.getMessage(), e); } } clustersCache = clusterEntities; } public static ClusterEntity getClusterEntity(ClusterSummary cluster, String cluster_name, int port) { int topology_num = cluster.get_topologies_size(); NimbusSummary ns = cluster.get_nimbus(); return getClusterEntity(ns, topology_num, cluster_name, port); } public static ClusterEntity getClusterEntity(NimbusSummary ns, int topology_num, String cluster_name, int port) { String ip = ns.get_nimbusMaster().get_host().split(":")[0]; ClusterEntity ce = new ClusterEntity(cluster_name, ns.get_supervisorNum(), topology_num, ip, port, ns.get_version(), ns.get_totalPortNum(), ns.get_usedPortNum()); return ce; } public static void flushClusterConfig() { Map<String, ClusterConfig> configMap = new HashMap<>(); //ui.cluster List<Map> uiClusters = ConfigExtension.getUiClusters(uiConfig); if (uiClusters != null && uiClusters.size() > 0) { for (Map cluster : uiClusters) { String zkRoot = ConfigExtension.getUiClusterZkRoot(cluster); String clusterName = ConfigExtension.getUiClusterName(cluster); if (clusterName == null) clusterName = parseClusterName(zkRoot); List<String> zkServers = ConfigExtension.getUiClusterZkServers(cluster); Integer zkPort = ConfigExtension.getUiClusterZkPort(cluster); ClusterConfig conf = new ClusterConfig(zkRoot, zkServers, zkPort); if (isInitialized) { Map<String, Object> nimbusConf = getNimbusConf(clusterName); Integer nimbusPort = ConfigExtension.getNimbusDeamonHttpserverPort(nimbusConf); Integer supervisorPort = ConfigExtension.getSupervisorDeamonHttpserverPort(nimbusConf); conf.setNimbusPort(nimbusPort); conf.setSupervisorPort(supervisorPort); } if (conf.isAvailable()) { configMap.put(clusterName, conf); } } } else { String zkRoot = (String) uiConfig.get(Config.STORM_ZOOKEEPER_ROOT); String clusterName = ConfigExtension.getClusterName(uiConfig); if (clusterName == null) clusterName = parseClusterName(zkRoot); List<String> zkServers = (List<String>) uiConfig.get(Config.STORM_ZOOKEEPER_SERVERS); Integer zkPort = JStormUtils.parseInt(uiConfig.get(Config.STORM_ZOOKEEPER_PORT)); ClusterConfig conf = new ClusterConfig(zkRoot, zkServers, zkPort); if (isInitialized) { Map<String, Object> nimbusConf = getNimbusConf(clusterName); conf.setNimbusPort(ConfigExtension.getNimbusDeamonHttpserverPort(nimbusConf)); conf.setSupervisorPort(ConfigExtension.getSupervisorDeamonHttpserverPort(nimbusConf)); } if (conf.isAvailable()) { configMap.put(clusterName, conf); } } clusterConfig = configMap; isInitialized = true; LOG.debug("nimbus config: " + clusterConfig); } private static String parseClusterName(String zkRoot) { if (zkRoot == null) { return UIDef.DEFAULT_CLUSTER_NAME; } else if (zkRoot.startsWith("/")) { return zkRoot.substring(1); } else { return zkRoot; } } public static String getHostIp(String ipPort) { if (ipPort.contains(":")) { String firstPart = ipPort.substring(0, ipPort.indexOf(":")); String lastPart = ipPort.substring(ipPort.indexOf(":")); return NetWorkUtils.ip2Host(firstPart) + lastPart; } else { return NetWorkUtils.ip2Host(ipPort); } } public static String getHost(String ipPort) { if (ipPort.contains(":")) { String firstPart = ipPort.substring(0, ipPort.indexOf(":")); return NetWorkUtils.ip2Host(firstPart); } else { return NetWorkUtils.ip2Host(ipPort); } } public static String getIp(String hostPort) { if (hostPort.contains(":")) { String firstPart = hostPort.substring(0, hostPort.indexOf(":")); return NetWorkUtils.host2Ip(firstPart); } else { return NetWorkUtils.host2Ip(hostPort); } } public static String getPort(String hostPort) { if (hostPort.contains(":")) { String lastPart = hostPort.substring(hostPort.indexOf(":")); return lastPart; } else { return null; } } public static Integer parseWindow(String windowStr) { Integer window; if (StringUtils.isBlank(windowStr)) { window = AsmWindow.M1_WINDOW; } else { window = Integer.valueOf(windowStr); } return window; } //to get nimbus client, we should reset ZK config public static Map resetZKConfig(Map conf, String clusterName) { ClusterConfig nimbus = clusterConfig.get(clusterName); if (nimbus == null) return conf; conf.put(Config.STORM_ZOOKEEPER_ROOT, nimbus.getZkRoot()); conf.put(Config.STORM_ZOOKEEPER_SERVERS, nimbus.getZkServers()); conf.put(Config.STORM_ZOOKEEPER_PORT, nimbus.getZkPort()); return conf; } public static Integer getNimbusPort(String name) { if (clusterConfig.containsKey(name)) { Integer port = clusterConfig.get(name).getNimbusPort(); if (port == null) { flushClusterConfig(); port = clusterConfig.get(name).getNimbusPort(); } return port; } LOG.info("can not find the cluster with name:" + name); return null; } public static Integer getSupervisorPort(String name) { if (clusterConfig.containsKey(name)) { Integer port = clusterConfig.get(name).getSupervisorPort(); if (port == null) { flushClusterConfig(); port = clusterConfig.get(name).getSupervisorPort(); } return port; } LOG.info("can not find the cluster with name:" + name); return null; } // change 20150812161819 to 2015-08-12 16:18 public static String prettyDateTime(String time) { if (time.length() < 12) return time; StringBuilder sb = new StringBuilder(); sb.append(time.substring(0, 4)).append("-").append(time.substring(4, 6)).append("-") .append(time.substring(6, 8)); sb.append(" ").append(time.substring(8, 10)).append(":").append(time.substring(10, 12)); return sb.toString(); } public static String prettyFileSize(long size) { if (size <= 0) return "0"; final String[] units = new String[] { "B", "KB", "MB", "GB", "TB" }; int digitGroups = (int) (Math.log10(size) / Math.log10(1024)); return new DecimalFormat("#,##0.#").format(size / Math.pow(1024, digitGroups)) + " " + units[digitGroups]; } //return the default value instead of throw an exception public static Long parseLong(String s, long defaultValue) { try { Long value = Long.parseLong(s); return value; } catch (NumberFormatException e) { //do nothing } return defaultValue; } // change 1441162320000 to "09-02 15:20" public static String parseDayTime(long ts) { return dayFormat.format(new Date(ts)); } public static String parseDateTime(long ts) { return dateFormat.format(new Date(ts)); } public static Map<String, Object> getNimbusConf(String clusterName) { NimbusClient client = null; try { client = NimbusClientManager.getNimbusClient(clusterName); String jsonConf = client.getClient().getNimbusConf(); Map<String, Object> nimbusConf = (Map<String, Object>) Utils.from_json(jsonConf); return nimbusConf; } catch (Exception e) { NimbusClientManager.removeClient(clusterName); LOG.error(e.getMessage(), e); return UIUtils.readUiConfig(); } } public static Map<String, Object> getTopologyConf(String clusterName, String topologyId) { NimbusClient client = null; try { client = NimbusClientManager.getNimbusClient(clusterName); String jsonConf = client.getClient().getTopologyConf(topologyId); Map<String, Object> topologyConf = (Map<String, Object>) Utils.from_json(jsonConf); return topologyConf; } catch (Exception e) { NimbusClientManager.removeClient(clusterName); LOG.error(e.getMessage(), e); return getNimbusConf(clusterName); } } public static Response getSupervisorConf(String host, int port) { String proxyUrl = "http://%s:%s/logview?cmd=showConf"; String url = String.format(proxyUrl, host, port); return getHttpResponse(url); } public static Response getJStack(String host, int port, int workerPort) { String proxyUrl = "http://%s:%s/logview?cmd=jstack&workerPort=%s"; String url = String.format(proxyUrl, host, port, workerPort); return getHttpResponse(url); } public static Response getFiles(String host, int port, String dir) { String url = String.format("http://%s:%s/logview?cmd=listDir&dir=%s", host, port, dir); return getHttpResponse(url); } public static Response getLog(String host, int port, String file, long position) { String url = String.format("http://%s:%s/logview?cmd=showLog&log=%s", host, port, file); if (position >= 0) { url += "&pos=" + position; } return getHttpResponse(url); } public static Response getHttpResponse(String url) { Response res; try { // 1. proxy call the task host log view service HttpClient client = HttpClientBuilder.create().build(); HttpPost post = new HttpPost(url); HttpResponse response = client.execute(post); int status = response.getStatusLine().getStatusCode(); String data = EntityUtils.toString(response.getEntity()); res = new Response(status, data); } catch (Exception e) { res = new Response(-1, e.getMessage()); } return res; } /** * gets a topology tree & nodes for topology graph utilization * * @param stormTopology jstorm sys-topology * @return a TopologyGraph */ public static TopologyGraph getTopologyGraph(StormTopology stormTopology, List<MetricInfo> componentMetrics) { Map<String, Bolt> bolts = stormTopology.get_bolts(); Map<String, SpoutSpec> spouts = stormTopology.get_spouts(); //remove system bolts String[] remove_ids = new String[] { "__acker", "__system", "__topology_master" }; for (String id : remove_ids) { bolts.remove(id); } //<id, node> Map<String, TopologyNode> nodes = Maps.newHashMap(); //<from:to,edge> Map<String, TopologyEdge> edges = Maps.newHashMap(); List<TreeNode> roots = Lists.newArrayList(); //this is used to get tree depth Map<String, TreeNode> linkMap = Maps.newHashMap(); //this is used to get tree depth // init the nodes for (Map.Entry<String, SpoutSpec> entry : spouts.entrySet()) { String componentId = entry.getKey(); nodes.put(componentId, new TopologyNode(componentId, componentId, true)); TreeNode node = new TreeNode(componentId); roots.add(node); linkMap.put(componentId, node); } for (Map.Entry<String, Bolt> entry : bolts.entrySet()) { String componentId = entry.getKey(); nodes.put(componentId, new TopologyNode(componentId, componentId, false)); linkMap.put(componentId, new TreeNode(componentId)); } //init the edges int edgeId = 1; for (Map.Entry<String, Bolt> entry : bolts.entrySet()) { String componentId = entry.getKey(); Bolt bolt = entry.getValue(); TreeNode node = linkMap.get(componentId); for (Map.Entry<GlobalStreamId, Grouping> input : bolt.get_common().get_inputs().entrySet()) { GlobalStreamId streamId = input.getKey(); String src = streamId.get_componentId(); if (nodes.containsKey(src)) { TopologyEdge edge = new TopologyEdge(src, componentId, edgeId++); edges.put(edge.getKey(), edge); // put into linkMap linkMap.get(src).addChild(node); node.addSource(src); node.addParent(linkMap.get(src)); } } } //calculate whether has circle boolean isFixed = false; while (!isFixed) { isFixed = true; for (TreeNode node : linkMap.values()) { for (TreeNode parent : node.getParents()) { if (!node.addSources(parent.getSources())) { isFixed = false; } } } } // fill value to edges fillTPSValue2Edge(componentMetrics, edges); fillTLCValue2Edge(componentMetrics, edges); // fill value to nodes fillValue2Node(componentMetrics, nodes); // calculate notes' depth int maxDepth = bfsDepth(roots); // set nodes level & get max breadth Map<Integer, Integer> counter = Maps.newHashMap(); int maxBreadth = 1; for (Map.Entry<String, TreeNode> entry : linkMap.entrySet()) { int layer = entry.getValue().getLayer(); nodes.get(entry.getKey()).setLevel(layer); int breadth = 1; if (counter.containsKey(layer)) { breadth = counter.get(layer) + 1; } counter.put(layer, breadth); if (maxBreadth < breadth) { maxBreadth = breadth; } } //adjust graph for components in one line String PREFIX = "__adjust_prefix_"; int count = 1; for (TreeNode node : linkMap.values()) { int layer = node.getLayer(); node.setBreadth(counter.get(layer)); } for (TreeNode tree : linkMap.values()) { if (isInOneLine(tree.getChildren())) { String id = PREFIX + count++; TopologyNode node = new TopologyNode(id, id, false); node.setLevel(tree.getLayer() + 1); node.setIsHidden(true); nodes.put(id, node); TreeNode furthest = getFurthestNode(tree.getChildren()); TopologyEdge toEdge = new TopologyEdge(id, furthest.getComponentId(), edgeId++); toEdge.setIsHidden(true); edges.put(toEdge.getKey(), toEdge); TopologyEdge fromEdge = new TopologyEdge(tree.getComponentId(), id, edgeId++); fromEdge.setIsHidden(true); edges.put(fromEdge.getKey(), fromEdge); } } TopologyGraph graph = new TopologyGraph(Lists.newArrayList(nodes.values()), Lists.newArrayList(edges.values())); graph.setDepth(maxDepth); graph.setBreadth(maxBreadth); //create graph object return graph; } private static TreeNode getFurthestNode(List<TreeNode> children) { TreeNode the = children.get(0); for (TreeNode node : children) { if (node.getLayer() > the.getLayer()) { the = node; } } return the; } private static boolean isInOneLine(List<TreeNode> children) { if (children.size() <= 1) { return false; } for (TreeNode node : children) { if (node.getBreadth() != 1) { return false; } } return true; } // fill emitted num to nodes private static void fillValue2Node(List<MetricInfo> componentMetrics, Map<String, TopologyNode> nodes) { String NODE_DIM = MetricDef.EMMITTED_NUM; List<String> FILTER = Arrays.asList(MetricDef.EMMITTED_NUM, MetricDef.SEND_TPS, MetricDef.RECV_TPS); for (MetricInfo info : componentMetrics) { if (info == null) continue; for (Map.Entry<String, Map<Integer, MetricSnapshot>> metric : info.get_metrics().entrySet()) { String name = metric.getKey(); String[] split_name = name.split("@"); String metricName = UIMetricUtils.extractMetricName(split_name); String compName = UIMetricUtils.extractComponentName(split_name); TopologyNode node = nodes.get(compName); if (node != null && FILTER.contains(metricName)) { for (Map.Entry<Integer, MetricSnapshot> winData : metric.getValue().entrySet()) { node.putMapValue(metricName, winData.getKey(), UIMetricUtils.getMetricValue(winData.getValue())); } } if (metricName == null || !metricName.equals(NODE_DIM)) { continue; } //get 60 window metric MetricSnapshot snapshot = metric.getValue().get(AsmWindow.M1_WINDOW); if (node != null) { node.setValue(snapshot.get_longValue()); nodes.get(compName).setTitle("Emitted: " + UIMetricUtils.getMetricValue(snapshot)); } } } } //fill tuple life cycle time to edges private static void fillTLCValue2Edge(List<MetricInfo> componentMetrics, Map<String, TopologyEdge> edges) { String EDGE_DIM = "." + MetricDef.TUPLE_LIEF_CYCLE; for (MetricInfo info : componentMetrics) { if (info == null) continue; for (Map.Entry<String, Map<Integer, MetricSnapshot>> metric : info.get_metrics().entrySet()) { String name = metric.getKey(); String[] split_name = name.split("@"); String metricName = UIMetricUtils.extractMetricName(split_name); // only handle with `.TupleLifeCycle` metrics if (metricName == null || !metricName.contains(EDGE_DIM)) { continue; } String componentId = UIMetricUtils.extractComponentName(split_name); String src = metricName.split("\\.")[0]; String key = src + ":" + componentId; //get 60 window metric MetricSnapshot snapshot = metric.getValue().get(AsmWindow.M1_WINDOW); TopologyEdge edge = edges.get(key); if (edge != null) { double value = snapshot.get_mean() / 1000; edge.setCycleValue(value); edge.appendTitle("TupleLifeCycle: " + UIMetricUtils.format.format(value) + "ms"); for (Map.Entry<Integer, MetricSnapshot> winData : metric.getValue().entrySet()) { // put the tuple life cycle time , unit is ms double v = winData.getValue().get_mean() / 1000; edge.putMapValue(MetricDef.TUPLE_LIEF_CYCLE + "(ms)", winData.getKey(), UIMetricUtils.format.format(v)); } } } } } private static void fillTPSValue2Edge(List<MetricInfo> componentMetrics, Map<String, TopologyEdge> edges) { String EDGE_DIM = "." + MetricDef.RECV_TPS; for (MetricInfo info : componentMetrics) { if (info == null) continue; for (Map.Entry<String, Map<Integer, MetricSnapshot>> metric : info.get_metrics().entrySet()) { String name = metric.getKey(); String[] split_name = name.split("@"); String metricName = UIMetricUtils.extractMetricName(split_name); // only handle with `.RecvTps` metrics if (metricName == null || !metricName.contains(EDGE_DIM)) { continue; } String componentId = UIMetricUtils.extractComponentName(split_name); String src = metricName.split("\\.")[0]; String key = src + ":" + componentId; //get 60 window metric MetricSnapshot snapshot = metric.getValue().get(AsmWindow.M1_WINDOW); TopologyEdge edge = edges.get(key); if (edge != null) { edge.setValue(snapshot.get_m1()); edge.setTitle("TPS: " + UIMetricUtils.format.format(edges.get(key).getValue())); for (Map.Entry<Integer, MetricSnapshot> winData : metric.getValue().entrySet()) { edge.putMapValue("TPS", winData.getKey(), UIMetricUtils.getMetricValue(winData.getValue())); } } } } } private static int bfsDepth(List<TreeNode> roots) { LinkedList<TreeNode> queue = Lists.newLinkedList(); for (TreeNode root : roots) { root.setLayer(0); queue.push(root); } int depth = 0; while (!queue.isEmpty()) { TreeNode cur = queue.poll(); if (cur.getLayer() > depth) { depth = cur.getLayer(); } for (TreeNode n : cur.getChildren()) { int newLayer = cur.getLayer() + 1; if (!n.isVisited() || n.getLayer() < newLayer) { if (!n.inCircle(cur)) { //n and cur is not in loop n.setLayer(newLayer); if (!queue.contains(n)) { queue.push(n); } } else if (n.addLoopNode(cur)) { // loop nodes only set layer once. n.setLayer(newLayer); } } } } return depth; } public static List<ChartSeries> getChartSeries(List<MetricInfo> infos, int window) { Map<String, ChartSeries> chartMap = Maps.newHashMap(); for (MetricInfo info : infos) { for (Map.Entry<String, Map<Integer, MetricSnapshot>> metric : info.get_metrics().entrySet()) { String name = metric.getKey(); String[] split_name = name.split("@"); String metricName = UIMetricUtils.extractMetricName(split_name); if (!metric.getValue().containsKey(window)) { LOG.info("snapshot {} missing window:{}", metric.getKey(), window); continue; } MetricSnapshot snapshot = metric.getValue().get(window); ChartSeries series; if (chartMap.containsKey(metricName)) { series = chartMap.get(metricName); } else { series = new ChartSeries(metricName); chartMap.put(metricName, series); } Number number = UIMetricUtils.getMetricNumberValue(snapshot); series.addData(number); if (metricName != null && metricName.equals(MetricDef.MEMORY_USED)) { series.addLabel(UIUtils.prettyFileSize(number.longValue())); } else { series.addLabel(UIMetricUtils.getMetricValue(snapshot)); } series.addCategory(UIUtils.parseDayTime(snapshot.get_ts())); } } return Lists.newArrayList(chartMap.values()); } public static void addWindowAttribute(ModelMap model, int window) { String DEFAULT = "label-default"; String PRIMARY = "label-primary"; String cls_60 = DEFAULT; String cls_600 = DEFAULT; String cls_7200 = DEFAULT; String cls_86400 = DEFAULT; switch (window) { case 60: cls_60 = PRIMARY; break; case 600: cls_600 = PRIMARY; break; case 7200: cls_7200 = PRIMARY; break; case 86400: cls_86400 = PRIMARY; break; } model.addAttribute("cls_60", cls_60); model.addAttribute("cls_600", cls_600); model.addAttribute("cls_7200", cls_7200); model.addAttribute("cls_86400", cls_86400); } public static void addErrorAttribute(ModelMap model, Exception e) { String errMsg = JStormUtils.getErrorInfo(e); String err = "!!!!!!!!!!!!!!!! Error:" + e.getMessage() + " !!!!!!!!!\r\n\r\n" + errMsg; model.addAttribute("error", err); } public static void addTitleAttribute(ModelMap model, String prefix) { String displayName; if (StringUtils.isBlank(prefix)) { displayName = UIDef.APP_NAME; } else { displayName = prefix + " - " + UIDef.APP_NAME; } model.addAttribute("title", displayName); model.addAttribute("PAGE_MAX", UIDef.PAGE_MAX); } }