Removing memory leak issue - java

I'm working on a maintenance project and a issue is raised for memory leak.
Basically the code is to load the values of data in application context from database. If the values in DB is changed then this functionality is used to update the value in application context also without restarting the server.
The variables annotated with #Value annotation are updated every where in the project, eg:
#Value("${cost}")
private String cost;
The method where memory leak is reported by production is updateObjects():
public class DbPropertySourcesPlaceholderConfigurer extends PropertyPlaceholderConfigurer {
private CustomBeanPostProcessor customBeanPostProcessor;
private static Properties dbProps = new Properties();
private void updateObjects() {
for (String key : customBeanPostProcessor.getObjectMap().keySet()) {
if (null != dbProps.get(key)) {
List<Object> objectList = customBeanPostProcessor.getObjectMap().get(key);
if (objectList != null && objectList.size() > 0) {
for (Object object : objectList) {
if (null != object) {
for (Field field : object.getClass().getDeclaredFields()) {
Value value = field.getAnnotation(Value.class);
if (null != value && null != value.value()
&& value.value().replace("${", "").replace("}", "").length() > 0
&& value.value().replace("${", "").replace("}", "").equalsIgnoreCase(key)
&& field.getType() == String.class) {
field.setAccessible(true);
try {
field.set(object, dbProps.get(key));
}
catch (IllegalAccessException ee) {
logger.error("Unable to update Object",ee);
}
}
}
}
}
}
}
}
}
Is it because of reflection used & can reflectionUtils of spring solve the problem?
CustomBeanPostProcessor.java
public class CustomBeanPostProcessor implements BeanPostProcessor {
public static Map<String, ArrayList<Object>> objectMap;
public Object postProcessBeforeInitialization(Object o, String string) throws BeansException {
return(o);
}
public Object postProcessAfterInitialization(Object o, String string) throws BeansException {
if(objectMap == null) {
objectMap = new HashMap<String, ArrayList<Object>>();
}
if(null == o) {
return(o);
}
if(AopUtils.isAopProxy(o) && o instanceof Advised) {
Class targetClass = ((Advised)o).getTargetClass();
Object object = null;
try {
Object target = ((Advised)o).getTargetSource().getTarget();
object = targetClass.cast(target);
for(Field field:object.getClass().getDeclaredFields()) {
Value value = field.getAnnotation(Value.class);
if(null != value && null != value.value() && value.value().replace("${", "").replace("}", "").length() > 0) {
updateObjectMap(value.value().replace("${", "").replace("}", ""), object);
}
}
}
catch(Exception ex) {
ex.printStackTrace();
}
}
else {
for(Field field:o.getClass().getDeclaredFields()) {
Value value = field.getAnnotation(Value.class);
if(null != value && null != value.value() && value.value().replace("${", "").replace("}", "").length() > 0) {
updateObjectMap(value.value().replace("${", "").replace("}", ""), o);
}
}
}
return(o);
}
public static void updateObjectMap(String key, Object object) {
ArrayList<Object> objectList = objectMap.get(key);
if(null == objectList) {
objectList = new ArrayList<Object>();
objectList.add(object);
objectMap.put(key, objectList);
}
else {
objectList.add(object);
}
}
public Map<String, ArrayList<Object>> getObjectMap() {
return objectMap;
}
public void setObjectMap(Map<String, ArrayList<Object>> objectMap) {
this.objectMap = objectMap;
}
}
Please let me know if more information is required.
Thank You.

Related

ConcurrentModifcationException happens occasionally

I have a function with a line that is supposedly meant to prevent a concurrent modification exception
List parseObjectKeys = new ArrayList<>(parseObject.keySet());
However it still happens every now and again
private static void convertParseObject(ParseObject parseObject,
HashMap<String, HashMap<String, WritableMap>> topLevel,
ArrayList<Task<Void>> tasks) {
if (parseObject != null) {
String className = parseObject.getClassName();
String id = parseObject.getObjectId();
if (!topLevel.containsKey(className)) {
topLevel.put(className, new HashMap<String, WritableMap>());
}
if (!topLevel.get(className).containsKey(id)) {
final WritableMap flatMap = Arguments.createMap();
flatMap.putString("class", className);
flatMap.putString("id", id);
if (parseObject.isDataAvailable()) {
topLevel.get(className).put(id, flatMap);
// This is required to prevent a ConcurrentModificationException
List<String> parseObjectKeys = new ArrayList<>(parseObject.keySet());
for (final String key : parseObjectKeys) {
Object value = parseObject.get(key);
if (value instanceof String) {
flatMap.putString(key, (String) value);
} else if (value instanceof Boolean) {
flatMap.putBoolean(key, (Boolean) value);
} else if (value instanceof Integer) {
flatMap.putInt(key, (Integer) value);
} else if (value instanceof Double) {
flatMap.putDouble(key, (Double) value);
} else if (value instanceof Date) {
flatMap.putString(key, Utils.toISO8601UTC((Date)value));
}
else {
if (value != null &&
!(value instanceof ParseACL)) {
Log.e(TAG, "Unknown type: " + value.getClass());
}
}
}
}
}
}
HashMap is not a thread-safe data structure, so you can use ConcurrentHashMap instead of HashMap.
use ConcurrentHashMap<String, ConcurrentHashMap<String, WritableMap>> topLevel
instead of
HashMap<String, HashMap<String, WritableMap>> topLevel.
and put List<String> parseObjectKeys = new ArrayList<>(parseObject.keySet());
in synchronized block.
Hope it will help.
Solution!!!
Add synchronized block like this
private synchronized void convertParseObject() { }

Syntax error on token "(", Type expected after this token

So I've run into some errors during this code, error is down where the keys are so
first but of code is where the error is, it's saying Syntax error on token "(" Type expected after this token, before I had string without the <> and then keys was underlined and the error was different... so not sure what to do.
Here is where the syntax error is:
for (<String> key : keys) {
Object out = map.get(key);
out = saveObject(out, field, cs, path + "." + key, depth);
subCS.set(key, out);
The whole file:
package me.kalo121;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.util.Vector;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
public abstract class ConfigObject
{
protected void onLoad(ConfigurationSection cs)
throws Exception
{
for (Field field : getClass().getDeclaredFields()) {
String path = field.getName().replaceAll("_", ".");
if (!doSkip(field))
{
if (cs.isSet(path))
field.set(this, loadObject(field, cs, path));
else
cs.set(path, saveObject(field.get(this), field, cs, path));
}
}
}
protected void onSave(ConfigurationSection cs) throws Exception {
for (Field field : getClass().getDeclaredFields()) {
String path = field.getName().replaceAll("_", ".");
if (!doSkip(field))
{
cs.set(path, saveObject(field.get(this), field, cs, path));
}
}
}
protected Object loadObject(Field field, ConfigurationSection cs, String path) throws Exception {
return loadObject(field, cs, path, 0);
}
protected Object saveObject(Object obj, Field field, ConfigurationSection cs, String path) throws Exception {
return saveObject(obj, field, cs, path, 0);
}
protected Object loadObject(Field field, ConfigurationSection cs, String path, int depth) throws Exception
{
#SuppressWarnings("rawtypes")
Class clazz = getClassAtDepth(field.getGenericType(), depth);
if ((ConfigObject.class.isAssignableFrom(clazz)) && (isConfigurationSection(cs.get(path))))
return getConfigObject(clazz, cs.getConfigurationSection(path));
if ((Location.class.isAssignableFrom(clazz)) && (isJSON(cs.get(path))))
return getLocation((String)cs.get(path));
if ((Vector.class.isAssignableFrom(clazz)) && (isJSON(cs.get(path))))
return getVector((String)cs.get(path));
if ((Map.class.isAssignableFrom(clazz)) && (isConfigurationSection(cs.get(path))))
return getMap(field, cs.getConfigurationSection(path), path, depth);
if ((clazz.isEnum()) && (isString(cs.get(path))))
return getEnum(clazz, (String)cs.get(path));
if ((List.class.isAssignableFrom(clazz)) && (isConfigurationSection(cs.get(path)))) {
#SuppressWarnings("rawtypes")
Class subClazz = getClassAtDepth(field.getGenericType(), depth + 1);
if ((ConfigObject.class.isAssignableFrom(subClazz)) || (Location.class.isAssignableFrom(subClazz)) || (Vector.class.isAssignableFrom(subClazz)) ||
(Map.class.isAssignableFrom(subClazz)) || (List.class.isAssignableFrom(subClazz)) || (subClazz.isEnum())) {
return getList(field, cs.getConfigurationSection(path), path, depth);
}
return cs.get(path);
}
return cs.get(path);
}
#SuppressWarnings("rawtypes")
protected Object saveObject(Object obj, Field field, ConfigurationSection cs, String path, int depth)
throws Exception
{
#SuppressWarnings("rawtypes")
Class clazz = getClassAtDepth(field.getGenericType(), depth);
if ((ConfigObject.class.isAssignableFrom(clazz)) && (isConfigObject(obj)))
return getConfigObject((ConfigObject)obj, path, cs);
if ((Location.class.isAssignableFrom(clazz)) && (isLocation(obj)))
return getLocation((Location)obj);
if ((Vector.class.isAssignableFrom(clazz)) && (isVector(obj)))
return getVector((Vector)obj);
if ((Map.class.isAssignableFrom(clazz)) && (isMap(obj)))
return getMap((Map)obj, field, cs, path, depth);
if ((clazz.isEnum()) && (isEnum(clazz, obj)))
return getEnum((Enum)obj);
if ((List.class.isAssignableFrom(clazz)) && (isList(obj))) {
Class subClazz = getClassAtDepth(field.getGenericType(), depth + 1);
if ((ConfigObject.class.isAssignableFrom(subClazz)) || (Location.class.isAssignableFrom(subClazz)) || (Vector.class.isAssignableFrom(subClazz)) ||
(Map.class.isAssignableFrom(subClazz)) || (List.class.isAssignableFrom(subClazz)) || (subClazz.isEnum())) {
return getList((List)obj, field, cs, path, depth);
}
return obj;
}
return obj;
}
#SuppressWarnings("rawtypes")
protected Class getClassAtDepth(Type type, int depth)
throws Exception
{
if (depth <= 0) {
String className = type.toString();
if ((className.length() >= 6) && (className.substring(0, 6).equalsIgnoreCase("class "))) {
className = className.substring(6);
}
if (className.indexOf("<") >= 0)
className = className.substring(0, className.indexOf("<"));
try
{
return Class.forName(className);
}
catch (ClassNotFoundException ex) {
if (className.equalsIgnoreCase("byte")) return Byte.class;
if (className.equalsIgnoreCase("short")) return Short.class;
if (className.equalsIgnoreCase("int")) return Integer.class;
if (className.equalsIgnoreCase("long")) return Long.class;
if (className.equalsIgnoreCase("float")) return Float.class;
if (className.equalsIgnoreCase("double")) return Double.class;
if (className.equalsIgnoreCase("char")) return Character.class;
if (className.equalsIgnoreCase("boolean")) return Boolean.class;
throw ex;
}
}
depth--;
ParameterizedType pType = (ParameterizedType)type;
Type[] typeArgs = pType.getActualTypeArguments();
return getClassAtDepth(typeArgs[(typeArgs.length - 1)], depth);
}
protected boolean isString(Object obj) {
if ((obj instanceof String)) {
return true;
}
return false;
}
protected boolean isConfigurationSection(Object o) {
try {
return (ConfigurationSection)o != null; } catch (Exception e) {
}
return false;
}
protected boolean isJSON(Object obj)
{
try {
if ((obj instanceof String)) {
String str = (String)obj;
if (str.startsWith("{")) {
return new JSONParser().parse(str) != null;
}
}
return false; } catch (Exception e) {
}
return false;
}
protected boolean isConfigObject(Object obj)
{
try {
return (ConfigObject)obj != null; } catch (Exception e) {
}
return false;
}
protected boolean isLocation(Object obj)
{
try {
return (Location)obj != null; } catch (Exception e) {
}
return false;
}
protected boolean isVector(Object obj)
{
try {
return (Vector)obj != null; } catch (Exception e) {
}
return false;
}
#SuppressWarnings("rawtypes")
protected boolean isMap(Object obj)
{
try
{
return (Map)obj != null; } catch (Exception e) {
}
return false;
}
#SuppressWarnings("rawtypes")
protected boolean isList(Object obj)
{
try
{
return (List)obj != null; } catch (Exception e) {
}
return false;
}
protected boolean isEnum(#SuppressWarnings("rawtypes") Class clazz, Object obj)
{
if (!clazz.isEnum()) return false;
for (Object constant : clazz.getEnumConstants()) {
if (constant.equals(obj)) {
return true;
}
}
return false;
}
protected ConfigObject getConfigObject(#SuppressWarnings("rawtypes") Class clazz, ConfigurationSection cs)
throws Exception
{
ConfigObject obj = (ConfigObject)clazz.newInstance();
obj.onLoad(cs);
return obj;
}
protected Location getLocation(String json) throws Exception {
JSONObject data = (JSONObject)new JSONParser().parse(json);
World world = Bukkit.getWorld((String)data.get("world"));
double x = Double.parseDouble((String)data.get("x"));
double y = Double.parseDouble((String)data.get("y"));
double z = Double.parseDouble((String)data.get("z"));
float pitch = Float.parseFloat((String)data.get("pitch"));
float yaw = Float.parseFloat((String)data.get("yaw"));
Location loc = new Location(world, x, y, z);
loc.setPitch(pitch);
loc.setYaw(yaw);
return loc;
}
protected Vector getVector(String json) throws Exception {
JSONObject data = (JSONObject)new JSONParser().parse(json);
double x = Double.parseDouble((String)data.get("x"));
double y = Double.parseDouble((String)data.get("y"));
double z = Double.parseDouble((String)data.get("z"));
return new Vector(x, y, z);
}
#SuppressWarnings({ "rawtypes", "unchecked" })
protected Map getMap(Field field, ConfigurationSection cs, String path, int depth) throws Exception
{
depth++;
Set keys = cs.getKeys(false);
Map map = new HashMap();
if ((keys != null) && (keys.size() > 0)) {
for (<String> key : keys) {
Object in = cs.get(key);
in = loadObject(field, cs, key, depth);
map.put(key, in);
}
}
return map;
}
protected List<String> getList(Field field, ConfigurationSection cs, String path, int depth) throws Exception
{
depth++;
int listSize = cs.getKeys(false).size();
String key = path;
if (key.lastIndexOf(".") >= 0) {
key = key.substring(key.lastIndexOf("."));
}
List<String> list = new ArrayList<String>();
if (listSize > 0) {
int loaded = 0;
int i = 0;
while (loaded < listSize) {
if (cs.isSet(key + i)) {
Object in = cs.get(key + i);
in = loadObject(field, cs, key + i, depth);
list.add((String) in);
loaded++;
}
i++;
if (i > listSize * 3) loaded = listSize;
}
}
return list;
}
#SuppressWarnings("rawtypes")
protected Enum getEnum(Class clazz, String string) throws Exception
{
if (!clazz.isEnum()) throw new Exception("Class " + clazz.getName() + " is not an enum.");
for (Object constant : clazz.getEnumConstants()) {
if (((Enum)constant).toString().equals(string)) {
return (Enum)constant;
}
}
throw new Exception("String " + string + " not a valid enum constant for " + clazz.getName());
}
protected ConfigurationSection getConfigObject(ConfigObject obj, String path, ConfigurationSection cs)
throws Exception
{
ConfigurationSection subCS = cs.createSection(path);
obj.onSave(subCS);
return subCS;
}
protected String getLocation(Location loc) {
String ret = "{";
ret = ret + "\"world\":\"" + loc.getWorld().getName() + "\"";
ret = ret + ",\"x\":\"" + loc.getX() + "\"";
ret = ret + ",\"y\":\"" + loc.getY() + "\"";
ret = ret + ",\"z\":\"" + loc.getZ() + "\"";
ret = ret + ",\"pitch\":\"" + loc.getPitch() + "\"";
ret = ret + ",\"yaw\":\"" + loc.getYaw() + "\"";
ret = ret + "}";
if (!isJSON(ret)) return getLocationJSON(loc); try
{
getLocation(ret);
} catch (Exception ex) {
return getLocationJSON(loc);
}
return ret;
}
#SuppressWarnings("unchecked")
protected String getLocationJSON(Location loc)
{
JSONObject data = new JSONObject();
data.put("world", loc.getWorld().getName());
data.put("x", String.valueOf(loc.getX()));
data.put("y", String.valueOf(loc.getY()));
data.put("z", String.valueOf(loc.getZ()));
data.put("pitch", String.valueOf(loc.getPitch()));
data.put("yaw", String.valueOf(loc.getYaw()));
return data.toJSONString();
}
protected String getVector(Vector vec) {
String ret = "{";
ret = ret + "\"x\":\"" + vec.getX() + "\"";
ret = ret + ",\"y\":\"" + vec.getY() + "\"";
ret = ret + ",\"z\":\"" + vec.getZ() + "\"";
ret = ret + "}";
if (!isJSON(ret)) return getVectorJSON(vec); try
{
getVector(ret);
} catch (Exception ex) {
return getVectorJSON(vec);
}
return ret;
}
#SuppressWarnings("unchecked")
protected String getVectorJSON(Vector vec)
{
JSONObject data = new JSONObject();
data.put("x", String.valueOf(vec.getX()));
data.put("y", String.valueOf(vec.getY()));
data.put("z", String.valueOf(vec.getZ()));
return data.toJSONString();
}
protected ConfigurationSection getMap(#SuppressWarnings("rawtypes") Map map, Field field, ConfigurationSection cs, String path, int depth) throws Exception
{
depth++;
ConfigurationSection subCS = cs.createSection(path);
#SuppressWarnings("rawtypes")
Set keys = map.keySet();
if ((keys != null) && (keys.size() > 0)) {
for (<String> key : keys) {
Object out = map.get(key);
out = saveObject(out, field, cs, path + "." + key, depth);
subCS.set(key, out);
}
}
return subCS;
}
protected ConfigurationSection getList(#SuppressWarnings("rawtypes") List list, Field field, ConfigurationSection cs, String path, int depth) throws Exception
{
depth++;
ConfigurationSection subCS = cs.createSection(path);
String key = path;
if (key.lastIndexOf(".") >= 0) {
key = key.substring(key.lastIndexOf("."));
}
if ((list != null) && (list.size() > 0)) {
for (int i = 0; i < list.size(); i++) {
Object out = list.get(i);
out = saveObject(out, field, cs, path + "." + key + (i + 1), depth);
subCS.set(key + (i + 1), out);
}
}
return subCS;
}
protected String getEnum(#SuppressWarnings("rawtypes") Enum enumObj)
{
return enumObj.toString();
}
protected boolean doSkip(Field field)
{
return (Modifier.isTransient(field.getModifiers())) || (Modifier.isStatic(field.getModifiers())) || (Modifier.isFinal(field.getModifiers())) ||
(Modifier.isPrivate(field.getModifiers()));
}
}
for (<String> key : keys) { is invalid syntax. The reason for (String key : keys) { didn't work either is that the type of your keys variable is the raw Set, which means you can only iterate over it with for (Object key : keys) {.
If you change Set keys = cs.getKeys(false); to
Set<String> keys = cs.getKeys(false); (assuming this Set contains only Strings), the following with work :
for (String key : keys) {

Refactor the existing code :- put a portion of a code in a method and use that method

The existing fillModel method is as below
#Override
protected void fillModel(final Model model,
final List<FacebookChannelConfig> items) {
final Map<FacebookChannelConfig, Boolean> defaultConfigMap = Maps
.newHashMapWithExpectedSize(items.size());
for (FacebookChannelConfig channelConfig : items) {
if (configRepository.getDefault() != null
&& configRepository.getDefault().getId().toString()
.equals(channelConfig.getId().toString())) {
defaultConfigMap.put(channelConfig, Boolean.TRUE);
} else {
defaultConfigMap.put(channelConfig, Boolean.FALSE);
}
if (channelConfig.getOwner().getId().getId() != userContext
.getOrganization().getId().getId()) {
channelConfig.setName(channelConfig.getName() + "("
+ channelConfig.getOwner().getName() + ")");
}
}
model.addAttribute("isDefault", defaultConfigMap);
}
I have added the following code from above fillModel to *idDefault* method as above.
if (configRepository.getDefault() != null
&& configRepository.getDefault().getId().toString()
.equals(channelConfig.getId().toString())) {
defaultConfigMap.put(channelConfig, Boolean.TRUE);
} else {
defaultConfigMap.put(channelConfig, Boolean.FALSE);
}
I have the isDefault method which returns boolean values as below
private boolean isDefault(final List<FacebookChannelConfig> config) {
if (configRepository.getDefault() != null
&& configRepository.getDefault().getId().toString()
.equals(config.get(0).toString())) {
return true;
}
return false;
}
The above method isDefault is being used inside fillModel method as below
protected void fillModel(final Model model,
final List<FacebookChannelConfig> items) {
final Map<FacebookChannelConfig, Boolean> defaultConfigMap = Maps
.newHashMapWithExpectedSize(items.size());
for (FacebookChannelConfig channelConfig : items) {
defaultConfigMap.put(channelConfig, isDefault(items));
if (channelConfig.getOwner().getId().getId() != userContext.getOrganization().getId().getId()) {
channelConfig.setName(
channelConfig.getName() + "("
+ channelConfig.getOwner().getName()
+ ")");
}
}
model.addAttribute("isDefault", defaultConfigMap);
}
The above usage of defaultConfigMap.put(channelConfig, isDefault(items)); is not correct.
Pleas suggest
You use List where you wanted the element:
Maybe this could work:
private boolean isDefault(final FacebookChannelConfig channelConfig) {
if (configRepository.getDefault() != null
&& configRepository.getDefault().getId().toString()
.equals(channelConfig.getId().toString())) {
return true;
}
return false;
}
and use:
defaultConfigMap.put(channelConfig, isDefault(channelConfig));

Custom Annotation Processor - Detect Method with Annotations

I am trying to write an annotation Procssor to detect the methods that are annotated with the #PrintMethod annotation. For example in the test Class below, i want to print the codes within the test Method. Is there a way to do it?
From the AnnotationProcessor class stated below, i am only able get the method name but not the details of the method.
Test Class
public class test {
public static void main(String[] args) {
System.out.println("Args");
}
#PrintMethod
private boolean testMethod(String input) {
if(input!=null) {
return true;
}
return false;
}
}
Annotation Processor Class
public class AnnotationProcessor extends AbstractProcessor {
//......
#Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
//retrieve test Anntoation
Set<? extends Element> ann =roundEnv.getElementsAnnotatedWith(PrintMethod.class);
//Print the Method Name
for(Element e: ann) {
String msg="Element ee :"+ee.getSimpleName().toString();
processingEnv.getMessager().printMessage( javax.tools.Diagnostic.Kind.ERROR, msg, e);
}
}
}
I was curious about this too so I decided to try and figure it out. Turns out to be easier than I expected. All you need to do is leverage the Trees api out of the proprietary tools.jar library. I've made a quick annotation processor along these lines here: https://github.com/johncarl81/printMethod
Here's the meat of it:
#SupportedSourceVersion(SourceVersion.RELEASE_6)
#SupportedAnnotationTypes("org.printMethod.PrintMethod")
public class PrintMethodAnnotationProcessor extends AbstractProcessor {
private Trees trees;
#Override
public synchronized void init(ProcessingEnvironment processingEnv) {
super.init(processingEnv);
trees = Trees.instance(processingEnv); //initialize the Trees api.
}
#Override
public boolean process(Set<? extends TypeElement> typeElements, RoundEnvironment roundEnvironment) {
MethodPrintScanner visitor = new MethodPrintScanner();
for (Element e : roundEnvironment.getElementsAnnotatedWith(PrintMethod.class)) {
TreePath tp = trees.getPath(e);
// visit the annotated methods
visitor.scan(tp, trees);
}
return true;
}
#Override
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latestSupported();
}
}
And the MethodPrintScanner:
public class MethodPrintScanner extends TreePathScanner {
#Override
public Object visitMethod(MethodTree methodTree, Object o) {
System.out.println(methodTree);
return null;
}
}
You can see that we are able to visit the TreePath associated with the given annotated Element. For each method, we simply println() the methodTree which gives us the contents of the method.
Using your example, here's the output of the program during compilation:
#PrintMethod()
private boolean testMethod(String input) {
if (input != null) {
return true;
}
return false;
}
It's one thing to make it work in your IDE. But it's another to detect them once your code is packed inside jar files. The following code can manage both.
public static List<Class> getPackageClassListHavingAnnotation(String pPackageName,
Class<? extends Annotation> pAnnotation) throws Exception
{
try
{
List<Class> classList = getPackageClassList(pPackageName);
if ((pAnnotation == null) || (classList == null)) return classList;
List<Class> resultList = new ArrayList<Class>(classList.size());
outerLoop:
for (Class clazz : classList)
{
try
{
for (Method method : clazz.getMethods())
{
if (method.isAnnotationPresent(pAnnotation))
{
resultList.add(clazz);
continue outerLoop;
}
}
}
catch (Throwable e)
{
}
}
return (resultList.isEmpty()) ? null : resultList;
}
catch (Exception e)
{
return null;
}
}
It requires the following helper methods:
public static List<Class> getPackageClassList(String pPackageName) throws Exception
{
try
{
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
String path = pPackageName.replace('.', '/');
List<File> dirs = new ArrayList<File>();
List<JarFile> jars = new ArrayList<JarFile>();
Enumeration<URL> resources = classLoader.getResources(path);
if (resources != null)
{
String fileName;
URL resource;
File file;
while (resources.hasMoreElements())
{
resource = resources.nextElement();
fileName = resource.getFile();
if (fileName.contains("!"))
{
// jar file
resource = new URL(StringUtil.getArrayFromString(fileName, "!")[0]);
file = urlToFile(resource);
if (!file.exists()) continue;
jars.add(new JarFile(file));
}
else
{
// class file that is not in a jar file
file = urlToFile(resource);
if (!file.exists()) continue;
dirs.add(file);
}
}
}
List<Class> resultList = new ArrayList<Class>(1000);
List<Class> tmpClassList;
for (File directory : dirs)
{
tmpClassList = getPckDirClassList(directory, pPackageName);
if (tmpClassList != null) resultList.addAll(tmpClassList);
}
for (JarFile jar : jars)
{
tmpClassList = getPckJarClassList(jar, pPackageName);
if (tmpClassList != null) resultList.addAll(tmpClassList);
}
return (resultList.isEmpty()) ? null : resultList;
}
catch (Exception e)
{
return null;
}
}
private static List<Class> getPckJarClassList(JarFile pJar, String pPackageName)
{
if ((pJar == null) || (pPackageName == null)) return null;
List<Class> resultList = new ArrayList<Class>(100);
Enumeration<JarEntry> jarEntries = (pJar.entries());
JarEntry jarEntry;
String fullClassName;
while (jarEntries.hasMoreElements())
{
jarEntry = jarEntries.nextElement();
fullClassName = jarEntry.getName().replaceAll("/", ".");
if (!fullClassName.startsWith(pPackageName)) continue;
if (!fullClassName.endsWith(".class")) continue;
// do not do a Class.forName for the following path, this can crash the server
try
{
resultList.add(Class.forName(fullClassName.substring(0, fullClassName.length() - 6)));
}
catch (Throwable e)
{
}
}
return (resultList.isEmpty()) ? null : resultList;
}
/**
* Recursive method to find all classes in a package directory tree.
*/
private static List<Class> getPckDirClassList(File pDirectory, String pPackageName) throws ClassNotFoundException
{
try
{
if ((pDirectory == null) || (pPackageName == null)) return null;
if (!pDirectory.exists()) return null;
File[] files = pDirectory.listFiles();
if ((files == null) || (files.length == 0)) return null;
List<Class> resultList = new ArrayList<Class>(100);
List<Class> tmpClassList;
for (File file : files)
{
if (file.isDirectory())
{
tmpClassList = getPckDirClassList(file, pPackageName + "." + file.getName());
if (tmpClassList != null) resultList.addAll(tmpClassList);
}
else if (file.getName().endsWith(".class"))
{
try
{
resultList.add(Class.forName(pPackageName + '.' + file.getName().substring(0, file.getName().length() - 6)));
}
catch (Throwable e)
{
}
}
}
return (resultList.isEmpty()) ? null : resultList;
}
catch (Exception e)
{
return null;
}
}
This code has been tested with .jar files on both windows and unix systems. It has also been tested with .java files in IntelliJ on windows.

which is best way to map servlet request parameters to a java class? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Easy way of populating Javabeans based on request parameters
Hi,
I have a Java Object with a set of search parameters, sth. like
public class SearchRequest {
private String customerName;
private String city;
...
}
This request has to be filled by a servet request.
But instead of writing code like
...
SearchRequest searchRequest = new SearchRequest();
if (request.getParameter("customerName") != null)
{
searchRequest.setCustomerName(request.getParameter("customerName"));
}
if (request.getParameter("city") != null)
{
searchRequest.setCity(request.getParameter("city"));
}
...
I'm looking for a more generic way.
I was checking the mapping tool Dozer but did not find a nice way how to handle this mapping.
Now I think reflection would be a choice.
Is this true?
If so does anyone has a code sniplet how this can be done with reflection?
I plead guilty:
public void save(HttpServletRequest req, Object obj) {
Set<String> names = new HashSet<String>();
#SuppressWarnings("unchecked")
Enumeration<String> enm = req.getParameterNames();
while (enm.hasMoreElements()) {
names.add(enm.nextElement());
}
Class clazz = obj.getClass();
while (clazz != Object.class && !names.isEmpty()) {
for (Field f: clazz.getDeclaredFields()) {
if (!Modifier.isTransient(f.getModifiers())) {
String name = f.getName();
if (names.contains(name)) {
try {
names.remove(name);
f.setAccessible(true);
Object val = convertValue(req, f.getType(),
name);
f.set(obj, val);
} catch (ParseException ex) {
LOG.error("Error assigning field", ex);
} catch (IllegalAccessException ex) {
LOG.error("Error assigning field", ex);
}
}
}
}
clazz = clazz.getSuperclass();
}
}
private Object convertValue(HttpServletRequest req, Class<?> type,
String name) throws ParseException {
if (type.isArray()) {
Class<?> elemType = type.getComponentType();
String strings[] = req.getParameterValues(name);
if (strings == null || strings.length == 0) {
return new Object[0];
}
Object array = Array.newInstance(elemType, strings.length);
for (int i = 0; i < strings.length; ++i) {
Object val = parse(elemType, strings[i]);
Array.set(array, i, val);
}
return array;
} else {
String s = req.getParameter(name);
if (s == null) {
return null;
}
return parse(type, s);
}
}
public static Object parse(Class<?> type, String value)
throws ParseException {
if (type == String.class) {
return value;
} else if (value == null || value.length() == 0) {
return null;
} else if (Enum.class.isAssignableFrom(type)) {
#SuppressWarnings("unchecked")
Object result = Enum.valueOf((Class<? extends Enum>)type, value);
return result;
} else if (type == boolean.class || type == Boolean.class) {
return "true".equals(value);
} else if (type == byte.class || type == Byte.class) {
return Byte.valueOf(value);
} else if (type == short.class || type == Short.class) {
return Short.valueOf(value);
} else if (type == int.class || type == Integer.class) {
return Integer.valueOf(value);
} else if (type == long.class || type == Long.class) {
return Long.valueOf(value);
} else if (type == float.class || type == Float.class) {
return Float.valueOf(value);
} else if (type == double.class || type == Double.class) {
return Double.valueOf(value);
} else if (type == Date.class) {
return new SimpleDateFormat("dd/MM/yyyy").parse(value);
} else if (type == BigDecimal.class) {
DecimalFormat format = getDecimalFormat("0.00");
return format.parse(value);
} else {
throw new RuntimeException("Cannot convert value of type " + type);
}
}
private static DecimalFormat getDecimalFormat(String pattern) {
DecimalFormatSymbols symbols = new DecimalFormatSymbols();
symbols.setDecimalSeparator('.');
DecimalFormat format = new DecimalFormat(pattern);
format.setParseBigDecimal(true);
format.setDecimalFormatSymbols(symbols);
return format;
}

Categories

Resources