BeanPropertyRowMapper cache problem on Tomcat - java

I am using my custom row mapper extended from BeanPropertyRowMapper to override underscoreName method. It was working well. I added new fields to DTO class and deployed to Tomcat again. But it couldn't map new fields. In BeanPropertyRowMapper's initialize method it is using BeanUtils.getPropertyDescriptors(mappedClass). I think the problem is due to not updated cache on deploy.
I tried to restart tomcat but it didn't work.
#Slf4j
public class ColumnRowMapper<T> extends BeanPropertyRowMapper<T> {
private ColumnRowMapper(final Class<T> mappedClass) {
super(mappedClass);
}
#Override
protected String underscoreName(final String name) {
Field declaredField = getField(getMappedClass(), name);
String columnName = getColumnName(declaredField);
return columnName == null ? super.underscoreName(name) : columnName.toLowerCase();
}
private Field getField(Class<?> clazz, String name) {
if (clazz == null) {
return null;
}
Field field = null;
try {
field = clazz.getDeclaredField(name);
} catch (Exception e) {
field = getField(clazz.getSuperclass(), name);
}
if (field == null) {
log.warn("Ups, field «{}» not found in «{}».", name, clazz);
}
return field;
}
private String getColumnName(Field declaredField) {
Column annotation;
String columnName;
if (declaredField == null || (annotation = declaredField.getAnnotation(Column.class)) == null
|| StringUtils.isEmpty(columnName = annotation.name())) {
return null;
}
return columnName;
}
public static <T> BeanPropertyRowMapper<T> newInstance(final Class<T> mappedClass) {
return new ColumnRowMapper<>(mappedClass);
}
}

Related

JPA Attribute Converter

I have some problem when I input value like this [] or [""] to insert data base.
It will infinity loop not stop.
I don't know why.
Example source code below.
#Entity("student")
class Student {
......
#Column(name = "something")
#Convert(converter = CustomConverter.class)
private List<String> something;
}
#Converter
public class CustomConverter implements AttributeConverter<List<String>, String> {
#Override
public String convertToDatabaseColumn(final List<String> param) {
if (param == null) {
return null;
} else if (param.isEmpty()) {
return null;
} else {
return String.join(",", param);
}
}
#Override
public List<String> convertToEntityAttribute(final String param) {
if (param == null) {
return null;
} else if (param.isEmpty()) {
return null;
} else {
return Arrays.asList(param.split(","));
}
}
But when I use value valid is working fine like this value ["vanda","nico"]
Question how to solve it and why this process loop forever ?
Thank you.

Java reflection with clone

Example I have data layer after
public class DemoData implements Cloneable {
private String name;
private String value;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
#Override
protected Object clone() throws CloneNotSupportedException {
return super.clone(); //To change body of generated methods, choose Tools | Templates.
}
}
I want to assign data values (DemoData) to a duplicate data (DemoData clone) layer as follows
public static void main(String[] args) {
DemoData demoData = new DemoData();
demoData.setName("Class Sources");
testReflectionDemo(demoData);
}
private static DemoData testReflectionDemo(DemoData demoData) {
try {
DemoData clone = (DemoData) demoData.clone();
clone.setName(demoData.getName());
clone.setValue(demoData.getValue());
return clone;
} catch (CloneNotSupportedException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
I want to convert the method testReflectionDemo(DemoData demoData) to method testReflectionDemo(T t) reflection as shown below.I do not know how to continue, please help me
public <T> T testReflectionDemo(T t){
Class<?> aClass = t.getClass();
for (Method method : aClass.getMethods()) {
}
return null;
}
Thank you all for the help for my question,I've removed the clone method, I just applied reflection.Hi #dabaicai.Your code helped me with the idea,I thought passing the value to the private field would be easier a little.
public static <T> T clazzClone(T t) throws InstantiationException, IllegalAccessException, NoSuchFieldException {
Class<?> clazzRoot = t.getClass();
Object newInstance = clazzRoot.newInstance();
Field[] fieldsClone = newInstance.getClass().getDeclaredFields();
for (Field fieldClone : fieldsClone) {
fieldClone.setAccessible(true);
fieldClone.set(newInstance, getContent(t, fieldClone.getName()));
}
return (T) newInstance;
}
private static String getContent(Object aClass, String name) throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
Field declaredField = aClass.getClass().getDeclaredField(name);
declaredField.setAccessible(true);
return (String) declaredField.get(aClass);
}
My program means when I need to edit user input data to output the results I want,with a common filter function
fieldClone.set(newInstance,methodYourEdit(getContent(t, fieldClone.getName())));
If the argument of testReflectionDemo is a javabean,it means that the class of argument have several a pair method of setXXX and 'getXXX,and thegetXXXdon't have argument,thesetXXX` just have one argument.If is this,the following code can copy the property from old object to new object.
Class<?> aClass = t.getClass();
Object result = aClass.newInstance();
Map<String,MethodHolder> map=new HashMap<>();
for (Method method : aClass.getMethods()) {
if(method.getName().startsWith("get") && method.getParameterTypes().length==0){
String property=method.getName().substring(3);
MethodHolder hodler = map.get(property);
if(hodler ==null){
map.put(property, new MethodHolder(property, method, null));
continue;
}
hodler.getMethod=method;
}else if (method.getName().startsWith("set") && method.getParameterTypes().length==1) {
String property=method.getName().substring(3);
MethodHolder holder = map.get(property);
if(holder ==null){
map.put(property, new MethodHolder(property, null, method));
continue;
}
holder.setMethod=method;
}
}
List<MethodHolder> collect = map.values().stream().filter(item -> item.setMethod != null && item.getMethod != null).collect(Collectors.toList());
for (MethodHolder holder : collect) {
Object property = holder.getMethod.invoke(t);
holder.setMethod.invoke(result,property);
}
return (T)result;
The MethodHolder just have some field:
public static class MethodHolder{
private String property;
private Method getMethod;
private Method setMethod;
public MethodHolder() {
}
public MethodHolder(String property, Method getMethod, Method setMethod) {
this.property = property;
this.getMethod = getMethod;
this.setMethod = setMethod;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof MethodHolder)) return false;
MethodHolder that = (MethodHolder) o;
return Objects.equals(property, that.property);
}
#Override
public int hashCode() {
return Objects.hash(property);
}
}
Pay attention of that the following code just make shallow copy.

It is possible to read the field value with annotations at runtime in java?

I have a class like follow, with MyAnnotation:
public class MyClass {
#MyAnnotation
public boolean bool;
public boolean getBool(){
return bool;
}
public voud setBool(boolean b){
bool = b;
}
}
It is possible to get the value of bool at runtime through the annotation?
EDIT:
this is that I was looking for:
public void validate(Object o) throws OperationNotSupportedException {
Field[] flds = o.getClass().getDeclaredFields();
for (Field field : flds) {
if (field.isAnnotationPresent(NotNull.class)) {
String fieldName = field.getName();
Method m;
Object value;
try {
m = o.getClass().getMethod("get" + capitalize(fieldName), null);
value = m.invoke(o, null);
if (value == null) {
throw new OperationNotSupportedException("Field '" + fieldName + "' must be initialized.");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
private String capitalize(final String line) {
return Character.toUpperCase(line.charAt(0)) + line.substring(1);
}
Not sure if this is what you're looking for but you can do something like this:
Object getValueForMyAnnotaion(MyClass obj) {
Field[] fieldList = obj.getClass().getDeclaredFields();
for (Field field : fieldList) {
if (field.isAnnotationPresent(MyAnnotation.class)) {
return field.get(obj);
}
}
}
Note that it will return Object and only for the first member that has the annotation but it can be easily changed to what you need.

entity can not be null?

I wanted to retrieve found object or a null from a database.
In my ProjectFollowerImpl, for a method useFollowingProject I return a single instance that matches the query, or null if the query returns no results.
#Override
public ProjectFollower userFollowingProject(Integer userId, Integer projectId) {
return (ProjectFollower) session.createCriteria(classType)
.add(Restrictions.eq("user.id", userId))
.add(Restrictions.eq("project.id", projectId))
.uniqueResult();
}
Then in a tapestry page, I have following methods:
public ProjectFollower getUserFollowingProject() {
return projectFollowerDao.userFollowingProject(loggedInUser.getId(), project.getId());
}
#CommitAfter
void onActionFromFollowProject() {
ProjectFollower pf = getUserFollowingProject();
if (pf != null) {
projectFollowerDao.delete(pf.getId());
} else {
pf = new ProjectFollower();
pf.setProjectId(project);
pf.setUserId(loggedInUser);
projectFollowerDao.merge(pf);
}
}
However, tapestry throws null pointer exception, stack trace:
com.rile.issuetracker.pages.Tracker getUserFollowingProject() Tracker.java 75
com.rile.issuetracker.pages.Tracker advised$onActionFromFollowProject_6d8b9673baf() Tracker.java 80
So why is it a problem to return a null value for a object? What am I doing wrong ?
UPDATE:
public class Tracker {
#Property
#SessionState
private User loggedInUser;
#Property
#Inject
private ProjectDao projectDao;
#Property
private Project projectP1, project;
#Property
private List<Project> projectList;
#Property
#Inject
private ProjectFollowerDao projectFollowerDao;
#Property
#Inject
private TicketDao ticketDao;
#Property
private List<Ticket> ticketList;
#Property
private Ticket ticketP1;
#Property
#Inject
private TicketFollowerDao ticketFollowerDao;
#Property
private Util util = new Util();
public boolean getLoggedIn() {
return loggedInUser.getEmail() != null;
}
#PageLoaded
void onPageLoad() {
projectList = projectDao.loadAll();
ticketList = ticketDao.loadAll();
}
void onActivate(Integer contextValue) {
if (contextValue != null) {
project = projectDao.getByID(contextValue);
}
if (project != null) {
List ticketListByProjectID = ticketDao.getTicketsByProjectID(project.getId());
if (!ticketListByProjectID.isEmpty()) {
ticketList = ticketListByProjectID;
} else {
ticketList = null;
}
}
}
public ProjectFollower getUserFollowingProject() {
return projectFollowerDao.userFollowingProject(loggedInUser.getId(), project.getId());
}
#CommitAfter
void onActionFromFollowProject() {
ProjectFollower pf = getUserFollowingProject();
if (pf != null) {
projectFollowerDao.delete(pf.getId());
} else {
pf = new ProjectFollower();
pf.setProjectId(project);
pf.setUserId(loggedInUser);
projectFollowerDao.merge(pf);
}
}
public boolean getIsUserFollowingTicket() {
return ticketFollowerDao.isUserFollowingTicket(loggedInUser.getId(), ticketP1.getId());
}
#CommitAfter
void onActionFromFollowTicket() {}
public String getActiveFor(String parameter) {
if (parameter == null || parameter.isEmpty()) {
return null;
}
switch (parameter) {
case "userFollowingProject":
return getUserFollowingProject() != null ? "active" : "null";
case "userFollowingTicket":
return getIsUserFollowingTicket() ? "anchor-active" : "anchor-inactive";
default:
return null;
}
}
}
From the complete code, it looks like the best bet is that project is null, after checking complete class, we see that its not injected, and its value is only set in onActivate function, if contextValue is not null and projectDao.getByID(contextValue) returns a non-null value.
Could you please confirm that is happenning correctly before the call to onActionFromFollowProject

XML Data Binding in Java MicroEdition

I have a J2ME Application in which i need to bind my XML response in J2ME.Will you please help me in this case?How to bind XML Data Binding in J2ME?
JiBX seems to support J2ME. See the following related JIRA issue: [#JIBX-110] Having a J2ME compatible official jibx release.
Once downloaded, you'll have to ant-build the j2me jars using the j2me target (ant j2me from the build directory where build.xml is sitting). You can just build it with a standard javac, no need for a specialized compiler (see this discussion in the JiBX users list).
It seems that what you want is to unmarshall an XML file to a Java class. If so, I have shared a generic way at my blog. It uses two classes to implement it. The code of the first class is:
public class XMLTag {
// if you do not have enough memory, use lazy
// instantiation on these attributes
private Hashtable attributes = new Hashtable();
private Vector childs = new Vector();
public void setAttributeValue(String attribute, String value) {
if (attribute != null && value != null) {
attributes.put(attribute, value);
}
}
public String getAttributeValue (String attribute) {
return (String) attributes.get(attribute);
}
public void addChild (XMLTag child) {
childs.addElement(child);
}
public Enumeration getChilds () {
return childs.elements();
}
public XMLTag getChildAt (int index) {
return (XMLTag) childs.elementAt(index);
}
}
Below is the source code of the second class:
class XMLBinder extends org.xml.sax.helpers.DefaultHandler {
private Hashtable map = new Hashtable();
private Stack stack = new Stack();
private XMLTag rootElement;
private String attribute;
private StringBuffer value = new StringBuffer();
/**
* #param map with String keys and XMLTag values
*/
public XMLBinder(Hashtable map) {
Enumeration e = map.keys();
while (e.hasMoreElements()) {
Object key = e.nextElement();
Object tag = map.get(key);
if (validateMapping(key, tag)) {
this.map.put(key, tag);
} else {
throw new IllegalArgumentException("key " + key);
}
}
}
private boolean validateMapping (Object key, Object tag) {
return key instanceof String
&& tag instanceof Class
&& XMLTag.class.isAssignableFrom((Class) tag);
}
public XMLTag unmarshall (InputStream in) throws IOException {
try {
SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
parser.parse(in, this);
return rootElement;
} catch (Exception ex) {
throw new IOException("caused by " + ex);
}
}
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
Class tag = (Class) map.get(qName);
if (tag != null) {
try {
XMLTag newTag = (XMLTag) tag.newInstance();
addAttributesToXMLTag(attributes, newTag);
stack.push(newTag);
} catch (Exception e) {
throw new SAXException("caused by " + e);
}
} else {
attribute = qName;
}
}
private void addAttributesToXMLTag (Attributes attributes, XMLTag newTag) {
if (attributes != null) {
for (int i = attributes.getLength() - 1; i >= 0; i--) {
String attrName = attributes.getQName(i);
String attrValue = attributes.getValue(i);
newTag.setAttributeValue(attrName, attrValue);
}
}
}
public void characters(char[] ch, int start, int length) {
if (attribute != null) {
value.append(ch, start, length);
}
}
public void endElement(String uri, String localName, String qName)
throws SAXException {
if (stack.isEmpty()) {
throw new SAXException("no mapping for " + qName);
}
if (attribute != null && attribute.equals(qName)) {
XMLTag parent = (XMLTag) stack.peek();
parent.setAttributeValue(attribute, value.toString());
attribute = null;
value.setLength(0);
} else {
XMLTag child = (XMLTag) stack.pop();
if (stack.isEmpty() == false) {
XMLTag parent = (XMLTag) stack.peek();
parent.addChild(child);
} else {
rootElement = (XMLTag) child;
}
}
}
}
To prevent the use of Class.forName we use a map with tags and classes. The key is a String with the tag name and the value is a Class that extends XMLTag. For example, reading an RSS feed would use below classes:
class RSS extends XMLTag {
Channel channel;
public void addChild(XMLTag child) {
if (child instanceof Channel) {
channel = (Channel) child;
}
}
}
class Channel extends XMLTag {
public void addChild(XMLTag child) {
if (child instanceof Item) {
super.addChild(child);
}
}
}
class Item extends XMLTag {
}
And the following map:
Hashtable map = new Hashtable();
map.put("rss", RSS.class);
map.put("channel", Channel.class);
map.put("item", Item.class);
The binder can then be used:
XMLBinder binder = new XMLBinder(map);
rss = (RSS) binder.unmarshall(in);
Update after comments
For your xml sample you need to create the following classes:
class DataTable extends XMLTag {
XsSchema xsSchema;
DiffgrDiffgram diffgrDiffgram;
public void addChild(XMLTag child) {
if (child instanceof XsSchema) {
xsSchema = (XsSchema) child;
}
else if (child instanceof DiffgrDiffgram) {
diffgrDiffgram = (DiffgrDiffgram) child;
}
}
}
class XsSchema extends XMLTag {
}
class DiffgrDiffgram extends XMLTag {
}
and use the following map
Hashtable map = new Hashtable();
map.put("DataTable", DataTable.class);
map.put("xs:schema", XsSchema.class);
map.put("diffgr:diffgram", DiffgrDiffgram.class);

Categories

Resources