WW-4516 Allows disable BeanInfo cache in devMode

This commit is contained in:
Lukasz Lenart
2015-06-26 21:45:30 +02:00
5 changed files with 172 additions and 43 deletions
@@ -20,12 +20,16 @@
*/
package org.apache.struts2.json;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.Result;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.util.ValueStack;
import com.opensymphony.xwork2.util.WildcardUtil;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -33,13 +37,12 @@ import org.apache.struts2.StrutsConstants;
import org.apache.struts2.StrutsStatics;
import org.apache.struts2.json.smd.SMDGenerator;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.Result;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.util.ValueStack;
import com.opensymphony.xwork2.util.WildcardUtil;
/**
* <!-- START SNIPPET: description --> <p/> This result serializes an action
@@ -84,6 +87,7 @@ public class JSONResult implements Result {
private boolean ignoreInterfaces = true;
private boolean enumAsBean = JSONWriter.ENUM_AS_BEAN_DEFAULT;
private boolean noCache = false;
private boolean cacheBeanInfo = true;
private boolean excludeNullProperties = false;
private String defaultDateFormat = null;
private int statusCode;
@@ -92,12 +96,18 @@ public class JSONResult implements Result {
private String contentType;
private String wrapPrefix;
private String wrapSuffix;
private boolean devMode = false;
@Inject(StrutsConstants.STRUTS_I18N_ENCODING)
public void setDefaultEncoding(String val) {
this.defaultEncoding = val;
}
@Inject(StrutsConstants.STRUTS_DEVMODE)
public void setDevMode(String val) {
this.devMode = BooleanUtils.toBoolean(val);
}
/**
* Gets a list of regular expressions of properties to exclude from the JSON
* output.
@@ -171,7 +181,10 @@ public class JSONResult implements Result {
ActionContext actionContext = invocation.getInvocationContext();
HttpServletRequest request = (HttpServletRequest) actionContext.get(StrutsStatics.HTTP_REQUEST);
HttpServletResponse response = (HttpServletResponse) actionContext.get(StrutsStatics.HTTP_RESPONSE);
// only permit caching bean information when struts devMode = false
cacheBeanInfo = !devMode;
try {
Object rootObject;
rootObject = readRootObject(invocation);
@@ -202,7 +215,7 @@ public class JSONResult implements Result {
protected String createJSONString(HttpServletRequest request, Object rootObject) throws JSONException {
String json = JSONUtil.serialize(rootObject, excludeProperties, includeProperties, ignoreHierarchy,
enumAsBean, excludeNullProperties, defaultDateFormat);
enumAsBean, excludeNullProperties, defaultDateFormat, cacheBeanInfo);
json = addCallbackIfApplicable(request, json);
return json;
}
@@ -20,20 +20,34 @@
*/
package org.apache.struts2.json;
import com.opensymphony.xwork2.util.TextParseUtil;
import com.opensymphony.xwork2.util.WildcardUtil;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.Writer;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.zip.GZIPOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.struts2.json.annotations.SMDMethod;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.lang.reflect.Method;
import java.util.*;
import java.util.regex.Pattern;
import java.util.zip.GZIPOutputStream;
import com.opensymphony.xwork2.util.TextParseUtil;
import com.opensymphony.xwork2.util.WildcardUtil;
/**
* Wrapper for JSONWriter with some utility methods.
@@ -41,19 +55,23 @@ import java.util.zip.GZIPOutputStream;
public class JSONUtil {
public final static String RFC3339_FORMAT = "yyyy-MM-dd'T'HH:mm:ss";
public static final boolean CACHE_BEAN_INFO_DEFAULT = true;
private static final Logger LOG = LogManager.getLogger(JSONUtil.class);
/**
* Serializes an object into JSON.
*
* @param object
* to be serialized
* @param cacheBeanInfo
* Specifies whether to cache bean info in the JSONWriter
* @return JSON string
* @throws JSONException
*/
public static String serialize(Object object) throws JSONException {
public static String serialize(Object object, boolean cacheBeanInfo) throws JSONException {
JSONWriter writer = new JSONWriter();
writer.setCacheBeanInfo(cacheBeanInfo);
return writer.write(object);
}
@@ -74,8 +92,33 @@ public class JSONUtil {
public static String serialize(Object object, Collection<Pattern> excludeProperties,
Collection<Pattern> includeProperties, boolean ignoreHierarchy, boolean excludeNullProperties)
throws JSONException {
return serialize(object, excludeProperties, includeProperties,
ignoreHierarchy, excludeNullProperties, CACHE_BEAN_INFO_DEFAULT);
}
/**
* Serializes an object into JSON, excluding any properties matching any of
* the regular expressions in the given collection.
*
* @param object
* to be serialized
* @param excludeProperties
* Patterns matching properties to exclude
* @param ignoreHierarchy
* whether to ignore properties defined on base classes of the
* root object
* @param cacheBeanInfo
* Specifies whether to cache bean info in the JSONWriter
* @return JSON string
* @throws JSONException
*/
public static String serialize(Object object, Collection<Pattern> excludeProperties,
Collection<Pattern> includeProperties, boolean ignoreHierarchy, boolean excludeNullProperties,
boolean cacheBeanInfo)
throws JSONException {
JSONWriter writer = new JSONWriter();
writer.setIgnoreHierarchy(ignoreHierarchy);
writer.setCacheBeanInfo(cacheBeanInfo);
return writer.write(object, excludeProperties, includeProperties, excludeNullProperties);
}
@@ -100,10 +143,38 @@ public class JSONUtil {
public static String serialize(Object object, Collection<Pattern> excludeProperties,
Collection<Pattern> includeProperties, boolean ignoreHierarchy, boolean enumAsBean,
boolean excludeNullProperties, String defaultDateFormat) throws JSONException {
return serialize(object, excludeProperties, includeProperties, ignoreHierarchy, enumAsBean,
excludeNullProperties, defaultDateFormat, CACHE_BEAN_INFO_DEFAULT);
}
/**
* Serializes an object into JSON, excluding any properties matching any of
* the regular expressions in the given collection.
*
* @param object
* to be serialized
* @param excludeProperties
* Patterns matching properties to exclude
* @param ignoreHierarchy
* whether to ignore properties defined on base classes of the
* root object
* @param enumAsBean
* whether to serialized enums a Bean or name=value pair
* @param defaultDateFormat
* date format used to serialize dates
* @param cacheBeanInfo
* Specifies whether to cache bean info in the JSONWriter
* @return JSON string
* @throws JSONException
*/
public static String serialize(Object object, Collection<Pattern> excludeProperties,
Collection<Pattern> includeProperties, boolean ignoreHierarchy, boolean enumAsBean,
boolean excludeNullProperties, String defaultDateFormat, boolean cacheBeanInfo) throws JSONException {
JSONWriter writer = new JSONWriter();
writer.setIgnoreHierarchy(ignoreHierarchy);
writer.setEnumAsBean(enumAsBean);
writer.setDateFormatter(defaultDateFormat);
writer.setCacheBeanInfo(cacheBeanInfo);
return writer.write(object, excludeProperties, includeProperties, excludeNullProperties);
}
@@ -118,7 +189,23 @@ public class JSONUtil {
* @throws JSONException
*/
public static void serialize(Writer writer, Object object) throws IOException, JSONException {
writer.write(serialize(object));
serialize(writer, object, CACHE_BEAN_INFO_DEFAULT);
}
/**
* Serializes an object into JSON to the given writer.
*
* @param writer
* Writer to serialize the object to
* @param object
* object to be serialized
* @param cacheBeanInfo
* Specifies whether to cache bean info in the JSONWriter
* @throws IOException
* @throws JSONException
*/
public static void serialize(Writer writer, Object object, boolean cacheBeanInfo) throws IOException, JSONException {
writer.write(serialize(object, cacheBeanInfo));
}
/**
@@ -138,7 +225,29 @@ public class JSONUtil {
public static void serialize(Writer writer, Object object, Collection<Pattern> excludeProperties,
Collection<Pattern> includeProperties, boolean excludeNullProperties) throws IOException,
JSONException {
writer.write(serialize(object, excludeProperties, includeProperties, true, excludeNullProperties));
serialize(writer, object, excludeProperties, includeProperties, excludeNullProperties, CACHE_BEAN_INFO_DEFAULT);
}
/**
* Serializes an object into JSON to the given writer, excluding any
* properties matching any of the regular expressions in the given
* collection.
*
* @param writer
* Writer to serialize the object to
* @param object
* object to be serialized
* @param excludeProperties
* Patterns matching properties to ignore
* @param cacheBeanInfo
* Specifies whether to cache bean info in the JSONWriter
* @throws IOException
* @throws JSONException
*/
public static void serialize(Writer writer, Object object, Collection<Pattern> excludeProperties,
Collection<Pattern> includeProperties, boolean excludeNullProperties, boolean cacheBeanInfo)
throws IOException, JSONException {
writer.write(serialize(object, excludeProperties, includeProperties, true, excludeNullProperties, cacheBeanInfo));
}
/**
@@ -74,6 +74,7 @@ public class JSONWriter {
private DateFormat formatter;
private boolean enumAsBean = ENUM_AS_BEAN_DEFAULT;
private boolean excludeNullProperties;
private boolean cacheBeanInfo = true;
/**
* @param object Object to be serialized into JSON
@@ -620,6 +621,10 @@ public class JSONWriter {
this.formatter = new SimpleDateFormat(defaultDateFormat);
}
}
public void setCacheBeanInfo(boolean cacheBeanInfo) {
this.cacheBeanInfo = cacheBeanInfo;
}
protected static class JSONAnnotationFinder {
private boolean serialize = true;
@@ -20,16 +20,6 @@
*/
package org.apache.struts2.json;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.mock.MockActionInvocation;
import com.opensymphony.xwork2.util.ValueStack;
import org.apache.struts2.StrutsStatics;
import org.apache.struts2.StrutsTestCase;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.mock.web.MockServletContext;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.SimpleDateFormat;
@@ -45,6 +35,18 @@ import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.StrutsStatics;
import org.apache.struts2.StrutsTestCase;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.mock.web.MockServletContext;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.mock.MockActionInvocation;
import com.opensymphony.xwork2.util.ValueStack;
/**
* JSONResultTest
*/
@@ -60,7 +62,7 @@ public class JSONResultTest extends StrutsTestCase {
Map map = new HashMap();
map.put("createtime", new Date());
try {
JSONUtil.serialize(map);
JSONUtil.serialize(map, JSONUtil.CACHE_BEAN_INFO_DEFAULT);
} catch (JSONException e) {
fail(e.getMessage());
}
@@ -45,7 +45,7 @@ public class JSONUtilTest extends TestCase {
bean1.setEnumField(AnEnum.ValueA);
bean1.setEnumBean(AnEnumBean.Two);
String json = JSONUtil.serialize(bean1);
String json = JSONUtil.serialize(bean1, JSONUtil.CACHE_BEAN_INFO_DEFAULT);
Map result = (Map) JSONUtil.deserialize(json);
assertEquals("str", result.get("stringField"));