Jettison / String returned as integer when marshalling - java

There's a 'feature' of Jettison, outlined in a JIRA entry way back in 2008, which refers to the following problem:
Let's say I ask the value of "element" to be "00102"; the output may look like follows:
{ "Response":
{ "element": "00102" }
}
but now I set "element" to be "102":
{ "Response":
{ "element": 102 }
}
I understand Jettison is trying to be helpful... but seriously, I don't need it to decide this sort of thing on my behalf. No-thank-you.
Current work-around
For the moment, I've used a solution outlined by the user here, who adds the following to the bean config:
<bean id="simpleConverter" class="org.codehaus.jettison.mapped.SimpleConverter"/>
<bean id="jsonProvider" class="org.apache.cxf.jaxrs.provider.JSONProvider">
<property name="typeConverter" ref="simpleConverter"/>
</bean>
This partly solves the issue, in so much as to say that all elements are forced to be strings even if they're clearly integers. Now, at least, I know exactly what structure my data is going to hold, and the element type is not going to change from a string to an integer and back again without my knowledge.
Problem
However, I'm unable to output another element now as an integer, even if I'd now wish to do so. It seems as if I can only force the output of elements to string across the entire service, rather than on a per-element basis.
Aside from the 'using Jackson' suggestions (which I can't follow, as the framework explicitly uses Jettison) are there any other ways I could specify which elements I'd like to force as a string in my JSON output?

The SimpleConverter also convert double and booleans to string, and that is a problem.
You can override the default converter only for your 'special' numbers. Unfortunately there is no way to see the context of original field to convert
public class MyConverter extends org.codehaus.jettison.mapped.DefaultConverter {
public Object convertToJSONPrimitive(String text) {
Object primitive = super.convertToJSONPrimitive(text);
//Apply your conversion rule;
if (primitive != null
&& primitive instanceof Long
&& text.startsWith("0"))
return text;
else
return primitive;
}
}
You can see the full code of DefaultConverter here
And the CXF configuration
<bean id="myConverter" class="MyConverter"/>
<bean id="jsonProvider" class="org.apache.cxf.jaxrs.provider.JSONProvider">
<property name="typeConverter" ref="myConverter"/>
</bean>

Related

XML base data validation rule in java

Hi I am completely new in XML in Java.In my recent project I need to create validation rules in XML,but the the problem is that different user group may have different rule
For example
<root>
<user-group type="sale">
<parameter-name ="loginName">
<max-length>10</max-length>
<min-length>4</min-length>
</parameter-name>
<parameter-name ="password">
<max-length>10</max-length>
<min-length>4</min-length>
</parameter-name>
</user-group>
<user-group type="clerk">
<parameter-name ="loginName">
<max-length>16</max-length>
<min-length>4</min-length>
</parameter-name>
<parameter-name ="password">
<max-length>12</max-length>
<min-length>8</min-length>
</parameter-name>
</user-group>`
</root>
So how to write a Java stuff to implements the above rule.
Thanks in advance.
Read the XML using one of the known XML parsers. Refer
XML Parsing for Java
As you read through the XML, you can create a data structure to store the rules. This is explained below.
Loop through each of the "user-group" XML nodes in your Java program, create a map implementation, you can use a HashMap, with key - "clerk" value will be a POJO bean defining a "rule"
For example here is your "Rules" class -
public class Rules {
private String ruleName;
private int maxLength;
private int minLength;
public String getRuleName() {
return ruleName;
}
public void setRuleName(String ruleName) {
this.ruleName = ruleName;
}
public int getMinLength() {
return minLength;
}
public void setMinLength(int minLength) {
this.minLength = minLength;
}
public void setMaxLength(int maxLength) {
this.maxLength = maxLength;
}
public int getMaxLength() {
return maxLength;
}
}
Now you can use this HashMap anywhere in your program, to implement the rules. Seems like you would need to implement rules on the UI. In that case, I would recommend using established frameworks like Struts, Spring or an equivalent framework.
Hope this gives you a headstart ;)
The simple answer: use XML schemas with define namespaces. This way each user-group type can define what the structure of that node is. Setting this as an attribute is not really the most effective way to do this. I can elaborate later tonight on how to use XSD with namespaces so that you could create a document with "different" user-group nodes, specified in different namespaces, that each entity could validate and use without any problems. I don't have time to show an example, but I found this: Creating an XML document using namespaces in Java
The most simplistic explanation I can come up with is the definition of "table". For a furniture store, a "table" entity has maybe a round or square surface with most likely 4 legs, etc. But a "table" could mean something completely different for some other group. Using your XML as an example, it would be something like this:
<root>
<sale:user-group xmlns:sale="SOME_URL">
<some structure and rules>
</sale:user-group>
<clerk:user-group xmlns:clerk="SOME_OTHER_URL">
<different structure and rules>
</clerk:user-group>
</root>
The link I provided should answer your question. If not, I will come back tonight and show you a simple XSD that might fit your case.

Spring Web Flow Converter

I have a Spring MVC and Web Flow 2.3 application.
All I would like to know is how you have a select box in SWF with some default value say, for example, 'Please Select' that is not bound to any value in the backing list.
In line with the docs I have created a conversion service:
public class ApplicationConversionServiceFactoryBean extends FormattingConversionServiceFactoryBean {
// formatters
registry.addFormatter(...);
// converters
registry.addConverter(...);
}
This all works unless I want to perform what would seem to be a perfectly simple task of having 'Please Select' in a select box.
A formatter cannot return null from its Parse Method so you cannot use that. Switching from a formatter to a one-way converter (String > Object) fixes then issue in the MVC stuff however the SWF still complains about missing converter for Object > String. Using this setup do I actually need to create another converter implementation for Object > String (essentially have two converters for every conversion).
Yes, there are other converters TwoWayConverter, ObjectToString etc. etc. however I do not see that these can be added in the above as they are all all the wrong type to be added using:
registry.addConverter(...);
The documentation around conversion is confusing to say the least:
http://docs.spring.io/spring-webflow/docs/2.3.x/reference/htmlsingle/spring-webflow-reference.html#converter-options
You can do atleast adding binding null value or empty string to your model. So you can use default value for select one menu. Like this:
<sf:option value="">Please select...</sf:option>
But in your Formatter or Converter, you should check your model property is null or empty String and if so return null or empty String as you like. Like this:
public YourEnum parse(String value, Locale local) throws ParseException {
if(YourEnum.valueOf(YourEnum.class, value.toUpperCase()) == YourEnum.VALUEONE) {
return YourEnum.VALUEONE;
} else if(YourEnum.valueOf(YourEnum.class, value.toUpperCase()) == YourEnum.VALUETWO) {
return YourEnum.VALUETWO;
} else {
return null;
}
}

Saving values of different types, with methods

I was to save some configuration values. :)
These values are might be defined in a xml file and might be of the types String, boolean, String[], ...
or others. These values might be defined in a xml file.
Is there a best practise way to save these values, together with their tagname in the xml file and a default value.
I want to clean up some ultra bad legacy code, where things look like this:
public static final String VIEWCOOKIE_MAXLENGTH_VALUENAME = "view_cookie_max_length";
public static final int VIEWCOOKIE_MAXLENGTH_DEFAULT = 512;
public static int viewCookie_maxLength = VIEWCOOKIE_MAXLENGTH_DEFAULT;
Integer temInt = basic.getTimedBaseIntegerValue(basic.c_adclear_section, null,
CookieValues.VIEWCOOKIE_MAXLENGTH_VALUENAME,
CookieValues.VIEWCOOKIE_MAXLENGTH_DEFAULT, currentTime);
if (firstLoad || basic.checkParamChanged(0,CookieValues.VIEWCOOKIE_MAXLENGTH_VALUENAME,
CookieValues.viewCookie_maxLength, temInt))
CookieValues.viewCookie_maxLength = temInt;
those lines for all values, and methods for all the different type.
Is there a better way like this:
public class Value<T> {
String valueName;
final T defaultValue;
T value;
Method method;
...
}
but I don't know if this is the best way and also I'm a little bit worried, because I don't want to slow down the server, due to all the Wrapppers. This problem is hard to search so I'm sorry if this has already been asked somewhere.
This might answer your question: What is the best way to convert a java object to xml with open source apis
Basically you have to use a Marshaller (something that converts an object to text and back), and there are tons of those for Java.

Spring Creates New Objects But Should Not

I'm having the following problem with Spring: I expected that singletons would be created once and then referenced from the Spring cache. But that does not seem to be the case. I have the following lines in my beans.xml:
<bean id="Cache" class="java.util.HashMap" scope="singleton" >
</bean>
which is referenced below like:
<bean id="ManuallyCachingDAO" class="blah"
scope="singleton" init-method="init" destroy-method="destroy">
<property name="cache" ref="Cache"></property>
...
and in the ManuallyCachingDAO the code:
public Object get(int id) {
Object o = cache.get(id);
if (o != null) {
return o;
}
// ... code for retrieving the object from the DB
}
but the HashMap gets emptied in mysterious ways sometimes! That is, I don't think it's actually emptied. I think it's just dropped and created anew when I reference the ManuallyCachingDAO in another class.
Could you tell me how to fix this problem?
EDIT: At Robin's hint: I do the following to get the beans in a lot of classes (not all though):
ClassPathResource blah = etc.;
XmlBeanFactory xbf = new XmlBeanFactory(blah);
...
xbf.getBean("Cache");
... right now I'm doing it (even for a lot of other beans) ... is that a very stupid or very bad idea or both? I think it occurs to me right now what I'm doing wrong... Until now, I just suspected that all XmlBeanFactories were somehow grabbing the same resources which might have been very dumb indeed, or could s/o tell me what's right?
I doubt that Spring is creating new HashMaps. Your configuration looks OK. I am pretty sure something is wrong in your logic.
In the part marked
// ... code for retrieving the object from the DB
do you actually write the retrieved values to the map?
Maybe concurrency is messing up your map. You don't want to use a HashMap as a singleton since it's not thread safe. Try using ConcurrentHashMap instead.
The config looks fine, and Spring is well tested in this respect so I don't think there are going to be any surprises there.
Would you by any chance be creating the Spring context each time you are trying to access the beans? Thereby recreating everything repeatedly.

How to ask BeanUtils to ignore null values

Using Commons beanUtils I would like to know how to ask any converter say the Dateconverter to ignore null values and use null as default. As an example consider a public class,
public class X {
private Date date1;
private String string1;
//add public getters and setters
}
and my convertertest as,
public class Apache {
#Test
public void testSimple() throws Exception {
X x1 = new X(), x2 = new X();
x1.setString1("X");
x1.setDate1(null);
org.apache.commons.beanutils.BeanUtils.copyProperties(x2, x1);
//throws ConversionException
System.out.println(x2.getString1());
System.out.println(x2.getDate1());
}
}
The above throws a NPE since the date happens to be null. This looks a very primitive scenario to me which should be handled by default (as in, I would expect x2 to have null value for date1). The doco tells me that I can ask the converter to do this. Can someone point me as to the best way for doing this ?
I dont want to get hold of the Converter and isUseDefault() to be true because then I have to do it for all Date, Enum and many other converters !
Apparently it looks like, there is a way to tell the ConvertUtils to not throw exceptions on null values which is achieved by calling
BeanUtilsBean.getInstance().getConvertUtils().register(false, false, 0);
The best solution is update to BeanUtils 1.9.0, since this problem is fixed as you can see here https://issues.apache.org/jira/browse/BEANUTILS-454
Maybe a little late but looks that you can register a DateConverter
https://issues.apache.org/jira/browse/BEANUTILS-387
I recently ran into this issue and just converted my variable to a string to avoid this error and converted it back to a date when needed. Not the most elegant solution, but for simplicity and to avoid problems like this, it's a viable solution. The other caveat was that BeanUtils would fire off it's methods before my classes would load, so I opted for this rather than a more complicated solution to the problem using custom classloaders.
By the way, prior to verion 1.8.0, BeanUtils itself would ignore these null values.
See this link:
No value specified for 'Date' when the field is a java.util.Date with a null value for a detailed explanation.
I am somewhat amazed that such a simple case as setting a null value in a bean, like this:
BeanUtils.setProperty(pojo, "date", null);
causes crashing behavior, as described above.
For what it's worth, here is my workaround:
import org.apache.commons.beanutils.BeanMap;
BeanMap beanMap = new BeanMap(pojo);
Method writeMethod = beanMap.getWriteMethod("date");
writeMethod.invoke(pojo, null);

Categories

Resources