I want to encrypt user input and store it in a database. I am using Struts 2 type conversion, all user input is treated as a String, and conversions such as the following work correctly:
String to Integer
String to Long
String to byte[]
But when I attempt a conversion to the target type: String, it does not work and the convertFromString() method is not invoked.
#Override
public Object convertFromString(Map context, String[] value, Class arg2) {
String val = value[0];
try {
return ASEEncDecUtil.encrypt(val.getBytes("UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return null;
}
}
I am unable to figure out what am I doing wrong.
Is there a best practice that should be used to encrypt user input?
You are most probably extending StrutsTypeConverter class in your custom converter. In it the convertFromString and convertToString methods are called from the convertValue method which looks something like that:
public Object convertValue(Map context, Object o, Class toClass) {
if (toClass.equals(String.class)) {
return convertToString(context, o);
} else if (o instanceof String[]) {
return convertFromString(context, (String[]) o, toClass);
} else if (o instanceof String) {
return convertFromString(context, new String[]{(String) o}, toClass);
} else {
return performFallbackConversion(context, o, toClass);
}
}
So if toClass is String class then convertFromString is never called.
To achieve what you want, extend com.opensymphony.xwork2.conversion.impl.DefaultTypeConverter instead and override public Object convertValue(Map context, Object o, Class toClass) method.
The job of a Converter is to perform a conversion between different formats.
It is not the right tool to get an object in a format, perform a business on it and then returning it in the same format.
That said, for this kind of things you can use several mechanisms (orthogonal like Struts2 Interceptors and Java EE Decorators, or specific like Action Methods or even Mutators / Accessors), each one more appropriate according to factors like the number of times / places where you need to use them.
The easiest way (I'm a KISS paradigm fan) is the Accessors / Mutators way:
public class KeepItSimpleStupidAction extends ActionSupport {
#Inject Logger LOG;
private String text; // text is always encrypted inside the action
public String getText() { // but it can also be read decrypted by calling the getter
return ASEEncDecUtil.decrypt(text.getBytes("UTF-8"));
}
public void setText(String text) { // the setter automatically encrypts it
this.text = ASEEncDecUtil.encrypt(text.getBytes("UTF-8"));
}
public String execute() {
LOG.debug("text decrypted: " + getText());
LOG.debug("text encrypted: " + text);
return SUCCESS;
}
}
I'm using Hazelcast as a shared map in my application. My map is like that:
Map<String, MyObject>
and MyObject:
class MyObject implements Serializeble {
// Map FieldName -> FieldValue
Map<String, Object> myMap;
}
So I'd like to use Hazelcast distributed query support to query in my object. I've checked that Hazelcast uses get's method to retrieve the object value, but in my case I don't have a get, instead of I'd like to implement my own getField like:
Object getField(String fieldName) {
return myMap[fieldName];
}
And force Hazelcast to call this method. As a workaround, I've hacked Hazelcast code to use a CustomGetter in the class
/hazelcast/src/main/java/com/hazelcast/query/impl/ReflectionHelper.java
line 144:
if (localGetter == null) {
localGetter = new CustomFieldGetter(name, obj);
}
and here My CustomFieldGetter class:
static class CustomFieldGetter extends Getter {
final Object value;
final Class type;
final String fieldName;
CustomFieldGetter(String fieldName, Object obj) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
super(null);
this.fieldName = fieldName;
this.value = obj.getClass().getMethod("getField", String.class).invoke(obj, fieldName);
this.type = value.getClass();
}
#Override
Object getValue(Object obj) throws Exception {
return value;
}
#Override
Class getReturnType() {
return type;
}
#Override
boolean isCacheable() {
return false;
}
#Override
public String toString() {
return "FieldGetter [parent=" + parent + ", field=" + fieldName + "]";
}
}
Ok cool, after recompilation of Hazelcast, and using this new jar, I could reach queries using plain sql. But for pagingQueries I got some errors.
So my finally question is:
I'd like to avoid hack Hazelcast code (for further updates). Does Hazelcast has some supports on this issue? Is there any other solution for this problem?
PS: I'm using Hazelcast version -> hazelcast-3.3-RC3
Thanks in advance.
one option is to implement Portable interface. Then you could write each entry as a separate field. This assumes the entry value implements the Portable interface as well.
Look at the sample code how to use Portable.
Problem
I don't know the best way to model my data. I'm worried my current approach has gotten overly complex, and I want to correct it now before I base any more code off it.
Data to be Modeled
I have data sets that consist of 50+ different data items. Each item consists of:
a unique identifier int
a label String.
validation criteria (min, max, legal characters, etc...).
a value Float, Long, Integer, String, or Date.
The label and validation criteria for each item is the same in every data set. Only the values are dynamic. Order is not important.
Needed Usage Examples
Add data to the data set
dataSet.put(itemIdentifier, value);
Traverse and validate all non-null values in the data set
for (DataItem item : dataSet.values()) {
boolean valid = item.validate();
if (valid) {...}
}
Show the specified items in the given data sets
public void displayData(List<DataSet> dataSets, int... itemsIdentifiers) {...}
Implementation Attempt
My current implementation has an abstract Key class as the "key" to a map. Each type subclasses for its own validation needs. Then, inside the DataSet class, I have public static keys for each item.
abstract public class Key {
public int mId;
public String mLabel;
public Key(int id, String label) {...}
abstract public boolean validate(Object Value);
}
public class FloatKey extends Key {
private int mMin, mMax;
public Key(int id, String label, int min, int max) {...}
public boolean validate(Object Value) {...}
}
// one for each type
...
public class DataSet {
public static Key ITEM_A = new FloatKey(1, "item A", 0, 100);
public static Key ITEM_B = new DateKey(2, "item B", "January 1, 1990");
// ~50 more of these
private Map<Key, Object> mMap;
public void put(int itemId, Object value) {...}
public Set<Object> values() {...};
...
}
I don't like that when I pull values out of DataSet, I need to hold onto the value AND the key so I can do things like DataSet.ITEM_A.validate(someFloat). I also find myself using instanceof and casting frequently when I traverse objects in a set because I need to call subclass-only methods in some situations.
Edits for further clarification
Data items and their validation criteria will require occasional changes and so maintenance should be relatively easy / painless.
Although I could use the Key objects themselves as keys into the map, I will sometimes need to put these keys in a Bundle (part of the android API). I would rather use the label or id (in case labels are the same) to avoid making my Key class Parcelable.
What about this approach:
Create this interface:
interface Validable {
boolean isValid();
}
Then, all data items inherit the following class and implicitly the interface ::
abstract class DataItem implements Validable {
public DataItem(int id, String label, int min, int max) {
}
}
Configure each specific instance of DataItem via constructor parameters, passing the common and the distinct values:
class FloatItem extends DataItem {
public FloatItem(int id, String label, int min, int max, Float value) {
super(id, label, min, max);
// set the Float value here
}
#Override
public boolean isValid() {
// validate here
return true;
}
}
class DateItem extends DataItem {
public DateItem(int id, String label, int min, int max, Date value) {
super(id, label, min, max);
}
#Override
public boolean isValid() {
// validate here
return true;
}
}
The client code would assemble the objects like this::
List<Validable> items = Lists.<Validable>newArrayList(new FloatItem(0, "", 0, 0, Float.NaN),
new DateItem(0, "", 0, 0, new Date()));
(note the usage of Google Guava)
Calling code only needs to do this::
for (Validable validable : items) {
System.out.println(validable.isValid());
}
Please note that this approach requires you to first create 'target' objects, and then ask the question if they are valid. In other words, you are passing the valid-able parameters via constructor and then, you ask the object if it is valid. The object itself will answer the question using the validation criteria inside it...
I hope I understood your problem correctly.
I don't quite understand your goals with the design, so maybe not all of this is correct or directly useful to you, but it's some ideas to play with.
First I'd point out that there are lots of fields in the code you've shown that should be marked final. For example, Key.mId, Key.mLabel, FloatKey.mMin, FloatKey.mMax, all the DataSet.ITEM_X, and DataSet.mMap. Marking them final (1) conveys the intended behavior better, (2) prevents accidents where something like a Key's mId changes, and (3) might have marginal performance benefits.
I wonder why you need the numeric ID for each key/field? If they're required for interfacing with some external application or storage format which already defines those IDs, that makes sense, but if it's only for internal things like this method:
public void displayData(List<DataSet> dataSets, int... itemsIdentifiers) {...}
then that could be more meaningfully implemented using a list of String labels or Key objects, instead of the numeric IDs. Likewise, DataSet.put could possibly use the Key or label instead of the ID.
I find myself using instanceof and casting frequently when I traverse objects in a set
Making Key generic can eliminate some casts. (Well, they will still be present in the bytecode, but not in the source because the compiler will take care of it.) E.g.,
abstract public class Key<T> {
...
abstract public boolean validate(T Value);
}
public class FloatKey extends Key<Float> {
...
public boolean validate(Float value) { ... }
}
In the validate method, you thus avoid the need to cast value.
Also, I'm guessing you currently have a method on class DataSet like this:
public Object get(int itemId) { ... }
If you use the Key instead of numeric ID to retrieve values, and make the method generic, you'll often be able to avoid the need for callers to cast the return value (though the cast is still present inside the get method):
public <T> T get(Key<T> key) { ... }
I don't like that when I pull values out of DataSet, I need to hold onto the value AND the key so I can do things like DataSet.ITEM_A.validate(someFloat).
You could make a class for the value instead of the key. E.g.,
abstract public class Value<T> {
public final int id;
public final String label;
protected Value(int id, String label) {
this.id = id;
this.label = label;
}
abstract public T get();
abstract public void set(T value);
}
public class FloatValue extends Value<Float> {
private final float min, max;
private float value;
public FloatValue(int id, String label, float min, float max, float value) {
super(id, label);
this.min = min;
this.max = max;
set(value);
}
public Float get() { return value; }
public void set(Float value) {
if (value < min | value > max) throw new IllegalArgumentException();
this.value = value;
}
}
public class DataSet {
public final FloatValue itemA = new FloatValue(1, "item A", 0, 100, 0);
...
}
That solves the stated problem, and also eliminates the map lookup previously required on every get/set of a value. However it has the side effect of duplicating the storage for the labels and numeric IDs, as the Value classes are not static fields any more.
In this scenario, to access DataSet values by label (or ID?), you can use reflection to build a map. In class DataSet:
private final Map<String, Value<?>> labelMap = new HashMap<>();
{
for (Field f : DataSet.class.getFields()) {
if (Value.class.isAssignableFrom(f.getType())) {
Value<?> v;
try {
v = (Value<?>)f.get(this);
} catch (IllegalAccessException | IllegalArgumentException e) {
throw new AssertionError(e); // shouldn't happen
}
labelMap.put(v.label, v);
}
}
}
There's a subtlety here: if you subclass DataSet to represent different types of data, then the Value fields of the subclasses will not have been initialized yet at the time DataSet's initializer builds the map. So if you create subclasses of DataSet, you might need a protected init() method to be called from subclass constructors, to tell it to (re)build the map, which is a bit ugly but it would work.
You can re-use this map to provide convenient iteration of a DataSet's values:
public Collection<Value<?>> values() {
return Collections.unmodifiableCollection(labelMap.values());
}
A final idea: if you're using reflection anyway, it might be possible to use ordinary fields for the values, with annotation interfaces to implement their behavior.
import java.lang.annotation.*;
import java.lang.reflect.*;
public class DataSet {
#Label("item A") #ValidateFloat(min=0, max=100) public float itemA;
#Label("item B") public String itemB;
#Retention(RetentionPolicy.RUNTIME)
public static #interface Label {
String value();
}
#Retention(RetentionPolicy.RUNTIME)
public static #interface ValidateFloat {
float min();
float max();
}
public final class Value {
public final String label;
private final Field field;
protected Value(String label, Field field) {
this.label = label;
this.field = field;
}
public Object get() {
try {
return field.get(DataSet.this);
} catch (IllegalArgumentException | IllegalAccessException e) {
throw new AssertionError(e); // shouldn't happen
}
}
public void set(Object value) {
try {
field.set(DataSet.this, value);
} catch (IllegalArgumentException | IllegalAccessException e) {
throw new AssertionError(e); // shouldn't happen
}
}
public void validate() {
Object value = get();
// Test for presence of each validation rule and implement its logic.
// Ugly but not sure how best to improve this...
if (field.isAnnotationPresent(ValidateFloat.class)) {
float floatValue = (float)value;
ValidateFloat rule = field.getAnnotation(ValidateFloat.class);
if (floatValue < rule.min() || floatValue > rule.max()) {
//throw new Whatever();
}
}
//if (field.isAnnotationPresent(...)) {
// ...
//}
}
}
private final Map<String, Value> labelMap = new HashMap<>();
{
for (Field f : DataSet.class.getFields()) {
if (f.isAnnotationPresent(Label.class)) {
Value value = new Value(f.getAnnotation(Label.class).value(), f);
labelMap.put(value.label, value);
}
}
}
public Collection<Value> values() {
return Collections.unmodifiableCollection(labelMap.values());
}
}
This approach has different tradeoffs. Code that knows exactly what field it wants can access it directly. E.g., dataSet.itemA instead of dataSet.get(DataSet.ITEM_A). Code that needs to iterate multiple fields does so via the Value wrapper (would Property be a better class name? Or Item?), which encapsulates the ugliness of the field reflection code.
I also put the validation logic into the annotations. If there are lots of fields with very simple numeric limits, that works well. If it's too complex for that you'd be better off with a DataSet.validate method that accesses the fields directly. E.g,
public void validate() {
if (itemC < 10 || itemC > itemD) ...
}
Okay, one more idea:
public class DataSet {
public float itemA;
public String itemB;
public static abstract class Value<T> {
public final String label;
protected Value(String label) {
this.label = label;
}
public abstract T get();
public abstract void set(T value);
}
public Value<?>[] values() {
return new Value[] {
new Value<Float>("itemA") {
public Float get() {
return itemA;
}
public void set(Float value) {
itemA = value;
}
},
new Value<String>("itemB") {
public String get() {
return itemB;
}
public void set(String value) {
itemB = value;
}
},
};
}
}
This is simple (no annotations or reflection) but it's repetitive. Since you have "50+" fields, the repetitiveness is probably not ideal as it's easy when copy-pasting to slip up at some point, forgetting to replace itemX = value with itemY = value, but if you only need to write it once it might be acceptable. Validation code could go either on the Value class or the DataSet class.
we are creating a JSON REST client application that has to communicate with a service written in C#.
Most things like difference in dates etc are solved pretty easily with the FlexJson library.
But one thing doesn't: Enum values that are sent as an integer, which is the value received from the service, and that have to be mapped to their Java Enum value.
The Java enum is ok, we can convert integers to the enum as long as the value exists of course.
But we do not succeed to get the Flexjson to convert the value.
One of the Enums is called FormState
We wrote a custom Transformer let's call it OurEnumTransformer which extends AbstractTransformer and implements ObjectFactory.
Upon deserialization we add the .use(Enum.class, OurEnumTransformer), if we don't we get an error like:
Don't know how to convert 4 to enumerated constant of FormState
which makes sense as it is an integer and not a name of an enum value
But we add the .use(...) we keep getting an error on deserialization:
FormState lacks a no argument constructor. Flexjson will instantiate any protected, private, or public no-arg constructor.
But it does actually have a private parameterless constructor.
Another thing is that a breakpoint that is set in the OurEnumTransformer is never hit.
So can anyone help me why .use(Enum.class, OurEnumTransformer) does not work with an enum that has integer values?
The code of the enum and OurEnumTransformeris below
public enum FormState {
None(0),
EditMode(1),
SignedBySender(2),
AddedToRide(4),
SignedByTransporter(8),
SignedByReceiver(16),
DLT_UNKNOWN();
private int value;
private FormState() {
this.value= -1;
}
private FormState(int value) {
this.value= value;
}
public int getValue()
{
return value;
}
private static final Map<Integer, FormState> intToTypeMap = new HashMap<Integer, FormState>();
static
{
for(FormState type: FormState.values())
{
intToTypeMap.put(type.value, type);
}
}
public static FormState fromInt(int i) {
FormState type = intToTypeMap.get(Integer.valueOf(i));
if (type == null)
return FormState.DLT_UNKNOWN;
return type;
}
}
and the factory
public final class OurEnumTransformer extends AbstractTransformer implements
ObjectFactory {
#SuppressWarnings("rawtypes")
#Override
public Object instantiate(ObjectBinder context, Object value, Type targetType,
Class targetClass)
{
if(targetClass.equals(FormState.class))
return FormState.fromInt((Integer)value);
else if(targetClass.equals(TrajectState.class))
return TrajectState.fromInt((Integer)value);
else
throw new JSONException(String.format("%s: Don't know how to convert %s to enumerated constant of %s",
context.getCurrentPath(), value, targetType));
}
#Override
public void transform(Object arg0) {
// TODO Auto-generated method stub
}
}
finally the calling code:
List<JsonTrajectModel> result = null;
JSONDeserializer<List<JsonTrajectModel>> deser = new JSONDeserializer<List<JsonTrajectModel>>();
result = deser
.use(Date.class, dateTransformer)
.use("values", JsonTrajectModel.class)
.use(Enum.class, enumTransformer)
.deserialize(jsonData);
In the last code block jsonData is a valid JSON string and enumTransformer is the OurEnumTransformer instance.
A final remark, the dateTransformer used in this code does do its work.
Any help is appreciated.
I have been trying to create an XML using the simplexml library (v2.6.2)
http://simple.sourceforge.net/home.php
The XML I want to create has to hold an enum value, which should be case-sensitive. Following is the POJO :
package pojos;
public enum MyEnum {
NEW("new"),
OLD("old");
private final String value;
MyEnum(String v)
{
value = v;
}
public String value() {
return value;
}
public static MyEnum fromValue(String v) {
for (MyEnum c: MyEnum.values()) {
if (c.value.equals(v)) {
return c;
}
}
throw new IllegalArgumentException(v);
}
}
Following is the serializer code :
import java.io.File;
import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister;
import pojos.MyEnum;
public class TestEnum {
/**
* #param args
* #throws Exception
*/
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
Serializer serializer = new Persister();
MyEnum example = MyEnum.NEW;
File result = new File("myenum.xml");
serializer.write(example, result);
}
}
The resultant output :
<myEnum>NEW</myEnum>
The desired output :
<myEnum>new</myEnum>
How should I proceed ? I cannot change the variable name in the enum as it happens to be the keyword "new" !
Thanks.
After some investigation of the source code, i have discovered that the library uses interface Transform to transform values to Strings. The default behavior of enum transformations is defined by class EnumTransform. In order to customize that, you can define you own Transform class. The following version of Transform implementation would call toString() instead of the default name() on the enum objects.
class MyEnumTransform implements Transform<Enum> {
private final Class type;
public MyEnumTransform(Class type) {
this.type = type;
}
public Enum read(String value) throws Exception {
for (Object o : type.getEnumConstants()) {
if (o.toString().equals(value)) {
return (Enum) o;
}
}
return null;
}
public String write(Enum value) throws Exception {
return value.toString();
}
}
Transform objects are returned from match method by objects of Matcher interface. There could be several Matcher objects. The library tries them one by one until it finds one that returns a non-null Transformer object. You can define your own Matcher object and pass it as argument to the constructor of Persister class. This object will get the highest priority.
Persister serializer = new Persister(new Matcher() {
public Transform match(Class type) throws Exception {
if (type.isEnum()) {
return new MyEnumTransform(type);
}
return null;
}
});
Finally, you wont forget to define a toString method on your enum classes. Then the combination of codes above will do you the work of encoding enum objects using their toString values.
You should override toString()
#Override
public String toString() {
return this.value.toLowerCase();
}
Then write results using
serializer.write(example.toString(), result);
I would look at the serializer code and undestand what that is doing, as you have not annotated any of your fields...which (according to their docs) should throw an an exception.