Json Serialization accepts numeric input for boolean variable - java

I am developing a REST API using spring MVC.
One of the service is used to fetch the train details with some request object .
Request object :
TrainRequest implements Serializable {
private static final long serialVersionUID = 6280494678832642677L;
private String travelMonth;
private boolean departOnly;
}
I have used below request to test the service.
{
"travelMonth": "DEC2016",
"departOnly":0
}
I have seen that 0 is serialized and assigned to departOnly as false .Also I tested with other than 0 and got departOnly as true.
But I dont want to have numeric input for boolean variables.
Help me how to restrict in Spring validation or Java to have only true/false in defined boolean varaible.

TrainRequest implements Serializable {
private static final long serialVersionUID = 6280494678832642677L;
private String travelMonth;
private int departOnlyInt; // Serialized instead of departOnly
private transient boolean departOnly; // Not serialized
............................
private void writeObject(ObjectOutputStream o) throws IOException {
departOnlyInt = departOnly ? 1 : 0;
o.defaultWriteObject();
}
private void readObject(ObjectInputStream o) throws IOException,
ClassNotFoundException {
o.defaultReadObject();
switch(departOnlyInt) {
case 0:
departOnly = false; break;
case 1:
departOnly = true; break;
default:
throw new IOException ("Invalid boolean: " + departOnlyInt);
}
}
..................
}

Related

Stateful Complex event processing with apache flink

I want to detect if two events happen in a defined timeframe based on two events that have the same identifier. For example a DoorEvent looks like this:
<doorevent>
<door>
<id>1</id>
<status>open</status>
</door>
<timestamp>12345679</timestamp>
</doorevent>
<doorevent>
<door>
<id>1</id>
<status>close</status>
</door>
<timestamp>23456790</timestamp>
</doorevent>
My DoorEvent java class in the example below has the same structure.
I want to detect that door with id 1 closes within 5 minutes of opening. I try to use the Apache flink CEP library for this purpose. The incoming stream contains all open and close messages from lets say 20 doors.
Pattern<String, ?> pattern = Pattern.<String>begin("door_open").where(
new SimpleCondition<String>() {
private static final long serialVersionUID = 1L;
public boolean filter(String doorevent) {
DoorEvent event = new DoorEvent().parseInstance(doorevent, DataType.XML);
if (event.getDoor().getStatus().equals("open")){
// save state of door as open
return true;
}
return false;
}
}
)
.followedByAny("door_close").where(
new SimpleCondition<String>() {
private static final long serialVersionUID = 1L;
public boolean filter(String doorevent) throws JsonParseException, JsonMappingException, IOException {
DoorEvent event = new DoorEvent().parseInstance(doorevent, DataType.XML);
if (event.getDoor().getStatus().equals("close")){
// check if close is of previously opened door
return true;
}
return false;
}
}
)
.within(Time.minutes(5));
How do I save the state of door 1 as open in the door_open so that in the door_close step I know that door 1 is the one being closed and it is not some other door?
If you have Flink 1.3.0 and above its really straightforard what you want to do
Your pattern would look something like this:
Pattern.<DoorEvent>begin("first")
.where(new SimpleCondition<DoorEvent>() {
private static final long serialVersionUID = 1390448281048961616L;
#Override
public boolean filter(DoorEvent event) throws Exception {
return event.getDoor().getStatus().equals("open");
}
})
.followedBy("second")
.where(new IterativeCondition<DoorEvent>() {
private static final long serialVersionUID = -9216505110246259082L;
#Override
public boolean filter(DoorEvent secondEvent, Context<DoorEvent> ctx) throws Exception {
if (!secondEvent.getDoor().getStatus().equals("close")) {
return false;
}
for (DoorEvent firstEvent : ctx.getEventsForPattern("first")) {
if (secondEvent.getDoor().getEventID().equals(firstEvent.getDoor().getEventId())) {
return true;
}
}
return false;
}
})
.within(Time.minutes(5));
So basically you can use IterativeConditions and get the context for the first patterns which are matched and iterate over that list while comparing for the one you need and proceed as you want.
IterativeConditions are expensive and should be handled accordingly
For more information on conditions check here at Flink - Conditions

Special Field in JSON Data using Jackson

I have a data structure that has a special property. The data structure represents stock pricing data for the entire day. [So basically OLHC] In my current serialization routine and builder I currently support an "all" property. Which is a method in the builder that sets all of the OHLC prices to one single price.
Is there a way to set this up without having to have the property name of all?
On Serialization it should make the comparison and use all
On deserialization it should redirect to the all method in the builder.
Is this possible in Jackson?
Example:
The data structure looks like:
EODPrice
- Open
- Low
- Close
- High
Lets say we have the json: "{all: 5.00}" It would deserialize to Open: 5.00, low: 5.00, close: 5.00, and high: 5.00. If we were to serialize I would want to change the behavior so that if we have Open == Low == Close == High then we'd create one property called all. If that condition was not true, then we wouldn't serialize the "all" property at all.
The serialization part is definitely possible by using the annotation #JsonFilter which you can read about in the Jackson documentation.
Deserialization is standard Jackson by the use of #JsonCreator.
Filters can be applied to classes, methods and fields and you can write your own custom filter that handles the open, low, close, high problem.
Check this tutorial for an excellent introduction.
For a code sample, take a look at this. First, declare your EODPrice with the #JsonFilter annotation.
#JsonIgnoreProperties(ignoreUnknown = true) // required to skip the "all" attribute in the JSON
#JsonFilter("allFilter") // Specify the filter
public class EODPrice {
private final BigDecimal close;
private final BigDecimal high;
private final BigDecimal low;
private final BigDecimal open;
// Builder method, does not include "all"
#JsonCreator
public EODPrice(
#JsonProperty("open") final BigDecimal open,
#JsonProperty("low") final BigDecimal low,
#JsonProperty("close") final BigDecimal close,
#JsonProperty("high") final BigDecimal high) {
this.open = open;
this.low = low;
this.close = close;
this.high = high;
}
// This is not part of the JSON but puts the business logic in the POJO
#JsonIgnore
public boolean allFieldsEqual() {
return open.equals(low) && open.equals(close) && open.equals(high);
}
public BigDecimal getAll() {
if (allFieldsEqual()) {
return open;
}
return BigDecimal.ZERO;
}
public BigDecimal getClose() {
return close;
}
public BigDecimal getHigh() {
return high;
}
public BigDecimal getLow() {
return low;
}
public BigDecimal getOpen() {
return open;
}
}
The filter can look something like this:
private PropertyFilter allFilter = new SimpleBeanPropertyFilter() {
#Override
public void serializeAsField(
Object pojo,
JsonGenerator jgen,
SerializerProvider provider,
PropertyWriter writer) throws Exception {
// If it is not the "all" property, go on with normal serialization
if (!writer.getName().equals("all")) {
writer.serializeAsField(pojo, jgen, provider);
return;
}
// Else, check the special all-rule
final EODPrice eodPrice = (EODPrice) pojo;
if (eodPrice.allFieldsEqual()) {
// Only serialize if all fields are equal
writer.serializeAsField(pojo, jgen, provider);
}
}
#Override
protected boolean include(BeanPropertyWriter writer) {
return true;
}
#Override
protected boolean include(PropertyWriter writer) {
return true;
}
};
Finally, setup the mapper. This testcase illustrates that the filter kicks in:
#Test
public void testJsonRoundtrip() throws IOException {
final FilterProvider filters = new SimpleFilterProvider().addFilter("allFilter", allFilter);
final EODPrice eodPriceWithAll = new EODPrice(BigDecimal.ONE, BigDecimal.ONE, BigDecimal.ONE, BigDecimal.ONE);
final EODPrice eodPriceWithoutAll = new EODPrice(BigDecimal.TEN, BigDecimal.ONE, BigDecimal.ONE, BigDecimal.ONE);
final ObjectMapper mapper = new ObjectMapper();
mapper.setFilters(filters);
// First, test serialization
final String eodWithAllAsStr = mapper.writeValueAsString(eodPriceWithAll);
final String eodWithoutAllAsStr = mapper.writeValueAsString(eodPriceWithoutAll);
Assert.assertTrue(eodWithAllAsStr.contains("all"));
Assert.assertFalse(eodWithoutAllAsStr.contains("all"));
// Then, test deserialization
final EODPrice eodPriceWithAll2 = mapper.readValue(eodWithAllAsStr, EODPrice.class);
final EODPrice eodPriceWithoutAll2 = mapper.readValue(eodWithoutAllAsStr, EODPrice.class);
Assert.assertTrue(eodPriceWithAll2.allFieldsEqual());
Assert.assertFalse(eodPriceWithoutAll2.allFieldsEqual());
}
EDIT: After updates from the OP deserialization is added to the POJO. Furthermore, business logic is moved from the filter to the POJO.

Final field value not working in bytecode generation

I am trying to learn about how classes work. I am trying to add a final field to my class using this code
dout.writeShort(1);//field count
dout.writeShort(Modifier.PUBLIC|Modifier.STATIC|Modifier.FINAL);//modifiers
dout.writeShort(utfConstant("jjj"));//name
dout.writeShort(utfConstant("I"));//signature
dout.writeShort(1);//attribute count
dout.writeShort(utfConstant("ConstantValue"));//constant value attribute
dout.writeShort(2);//size of attribute
dout.writeShort(intConstant(8));//value
But i am getting this error when i try to compile it
Exception in thread "main" java.lang.ClassFormatError: Invalid ConstantValue field attribute length 131082 in class file Test
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:791)
at java.lang.ClassLoader.defineClass(ClassLoader.java:634)
at Bytecode.BytecodeTest$BytecodeClassLoader.buildClass(BytecodeTest.java:161)
at Bytecode.BytecodeTest.makeClass(BytecodeTest.java:39)
at Bytecode.BytecodeTest.buildClass(BytecodeTest.java:24)
at Bytecode.BytecodeTest.main(BytecodeTest.java:17)
Here is my other code
private void writeConstantPool(DataOutputStream dout) throws IOException
{
dout.writeShort(poolIndex);
for (Data data : poolMap)
{
int tag = (byte) data.getData()[0];
dout.writeByte(tag);
switch (tag)
{
case CONSTANT_Utf8:
dout.writeUTF((String) data.getData()[1]);
break;
case CONSTANT_Class:
dout.writeShort((Integer) data.getData()[1]);
break;
case CONSTANT_Integer:
dout.writeInt((Integer) data.getData()[1]);
break;
default:
throw new RuntimeException();
}
}
}
private int utfConstant(String s)
{
return constant(CONSTANT_Utf8, s);
}
private int intConstant(int i)
{
return constant(CONSTANT_Integer, i);
}
private int classConstant(String s)
{
int classNameIndex = utfConstant(s.replace('.', '/'));
return constant(CONSTANT_Class, classNameIndex);
}
private int constant(Object... data)
{
Data constantData = new Data(data);
if (poolMap.contains(constantData))
return poolMap.indexOf(constantData)+1;
poolMap.add(poolIndex-1, constantData);
return poolIndex++;
}
private final Stack<Data> poolMap = new Stack<Data>();
private int poolIndex = 1;
private static class Data
{
private Object[] data;
public Data(Object... data)
{
this.data = data;
}
public Object[] getData()
{
return data;
}
public boolean equals(Object o)
{
if(o instanceof Data)
{
Data other = (Data) o;
return Arrays.equals(data, other.getData());
}
return false;
}
}
The way im doing this is by generating all the methods and fields and then generating the constant pool, and then i am putting the constant pool in the byte array before the methods and fields.
Can anyone tell me what i am doing wrong i could show more code if necessary, additionally i think the problem might be with intConstant or the constant value attribute.
After looking at this with a bytecode editor it looks like the intConstant method works fine so i think it is the field code that isnt working. Also i looked at a constant in a bytecode editor and it looked the same i am confused.
I believe the length of an attribute is supposed to be a 32-bit integer, not a 16-bit short.

java loses values from ManagedBeans

I try to write an application to create PDF files, it uses the JavaServer Faces. I struggle with a problem when I give the value of the text box from bean to factory class, the values ​​are lost. I wonder why this happens, already tried many solutions, but they will cause expansion of the code and do not help.
Bean code:
#ManagedBean
#ViewScoped
public class PanelInneBean extends AbstractPanel implements Serializable {
private static final long serialVersionUID = 1L;
private final int CODE = 4;
private boolean use;
private String tytul, opis;
private PdfFactory pdf = PdfFactory.getPdfObject();
public PanelInneBean() {
use = false;
}
public boolean getUse() {
return use;
}
public String getTytul() {
return tytul;
}
public void setTytul(String tytul) {
this.tytul = tytul;
}
public String getOpis() {
return opis;
}
public void setOpis(String opis) {
this.opis = opis;
}
public int getCode() {
return CODE;
}
private void add() {
use = true;
}
public void addBean() {
add();
pdf.addElement(this);
System.out.println("InnePanel after pdf.addElement() this.opis:" + this.opis);
// This sysout prints the correct value after give object to factory
}
}
Factory piece of code:
public int addElement(PdfElement element) {
pdfType = true;
if (element.getUse()) {
elementList.add(element);
return 1;
}
return 0;
}
public void prepare() {
for (PdfElement element : elementList) {
System.out.println("element.code:" + element.getCode());
switch (element.getCode()) {
case 0:
if (nF != null)
break;
nF = new NaglowekFactory(element, Counter.getNumber());
break;
case 1:
if (pF != null)
break;
pF = new ProduktyFactory(element, Counter.getNumber());
prodSum = pF.getProdukty().getSuma();
euroData = pF.getProdukty().getEuroData();
break;
case 2:
if (mF != null)
break;
mF = new MontazFactory(element, Counter.getNumber());
servSum = mF.getMontaz().getSuma();
break;
case 3:
if (uF != null)
break;
uF = new UslugiFactory(element, Counter.getNumber());
asmSum = uF.getUslugi().getSuma();
break;
case 4:
if (iF != null)
break;
iF = new InneFactory(element, Counter.getNumber());
//here Opis value is empty
break;
}
}
System.out.println("factory.prepare() ->");
}
Constructor of InneFactory:
PanelInneBean inne;
public InneFactory(PdfElement element, int order) {
inne = (PanelInneBean) element;
System.out.println("innerFactory constructor, inne.getTytul(): "
+ inne.getTytul());
//here values are empty
this.order = order;
list = new ArrayList<Element>();
}
public int getOrder() {
return order;
}
what I'm doing wrong?
I think you are running into a common misconception about how #ViewScoped beans really work. The bean object itself is created on every Faces request and destroyed after every Faces response.
After the bean is re created however JSF will enter the first lifecycle phase RestoreView. During this phase it will fetch the last good values for this bean from the View State and apply them to the beans Managed Properties.
Basically what is happening is that you are invoking an action, which generates a seperate request than the one that loaded the page, and at this point the reference you added to the PdfFactory is now lost because the PdfFactory in the last object was destroyed!
The best way to resolve this would be to make PdfFactory a Managed Bean. You can initialize the factory in the #PostConstruct method and you can inject other Managed Beans into your PdfFactory bean using the #ManagedProperty annotation.
#ManagedBean
#RequestScoped
public PdfFactory extends ... implements Serializable {
#ManagedProperty("#{myViewBean}")
private MyViewBean viewBean;
#PostConstruct
public initializeFactory() {
//Do stuff
}
public void prepare() {
// prepare stuff
}
}

Enum-like structure with instances?

I use the following enum type:
enum Status {OK,TIMEOUT,EXCEPTION}
But now I want to store what exactly the Exception is. Unfortunately you cannot instantiate an enum type. What is the best way to make something like the following possible?
switch(status)
{
case(OK) {System.out.println("Everything OK!");break;}
case(TIMEOUT) {System.out.println("Timeout :-(");break;}
case(EXCEPTION) {System.out.println("We have an exception: "+status.exception);break;}
}
My ideas
Class with singletons
class Status
{
final Exception e;
public final Status OK = new Status(null);
public final Status TIMEOUT = new Status(null);
public Status(Exception e) {this.e=e;}
}
Then I could do:
if(status==Status.OK) {System.out.println("Everything OK!");}
else if(status==Status.TIMEOUT) {System.out.println("Timeout :-(");}
else {System.out.println("We have an exception: "+status.exception);}
2. Several Classes
class Status {}
class StatusOK extends Status {}
class StatusTimeout extends Status {}
class StatusException extends Status
{
final Exception e;
public StatusException(Exception e) {this.e=e;}
}
Then I would need a bunch of "instanceOf"-statements.
P.S.: OK it seems that I didn't explain it clearly enough. In my program I answer requests and I store the status of the processing of those requests:
Map<Request,Status> request2Status;
Thus I cannot use something like Status.getMessage(exception); because at that position in my code I do not know which exception it was. That why I want to save it inside the status.
Chosen solution
private static class LearnStatus implements Serializable
{
private static final long serialVersionUID = 1L;
public static final LearnStatus OK = new LearnStatus(null);
public static final LearnStatus TIMEOUT = new LearnStatus(null);
public static final LearnStatus NO_TEMPLATE_FOUND = new LearnStatus(null);
public static final LearnStatus QUERY_RESULT_EMPTY = new LearnStatus(null);
public static final LearnStatus NO_QUERY_LEARNED = new LearnStatus(null);
public final Exception exception;
private LearnStatus(Exception exception) {this.exception = exception; }
public static LearnStatus exceptionStatus(Exception cause)
{
if (cause == null) throw new NullPointerException();
return new LearnStatus(cause);
}
#Override public String toString()
{
if(this==OK) {return "OK";}
if(this==TIMEOUT) {return "timeout";}
if(this==NO_TEMPLATE_FOUND) {return "no template found";}
if(this==QUERY_RESULT_EMPTY) {return "query result empty";}
if(this==NO_QUERY_LEARNED) {return "no query learned";}
return "<summary>Exception: <details>"+exception.getLocalizedMessage()+"</details></summary>";
}
}
Problems with that
If I serialize an object with Status.OK in it, after deserialization if(status==Status.OK) does not work anymore.
New solution
I now included an enum type within the class. What do you think about it?
private static class LearnStatus implements Serializable
{
public enum Type {OK, TIMEOUT, NO_TEMPLATE_FOUND,QUERY_RESULT_EMPTY,NO_QUERY_LEARNED,EXCEPTION}
public final Type type;
private static final long serialVersionUID = 1L;
public static final LearnStatus OK = new LearnStatus(Type.OK,null);
public static final LearnStatus TIMEOUT = new LearnStatus(Type.TIMEOUT,null);
public static final LearnStatus NO_TEMPLATE_FOUND = new LearnStatus(Type.NO_TEMPLATE_FOUND,null);
public static final LearnStatus QUERY_RESULT_EMPTY = new LearnStatus(Type.QUERY_RESULT_EMPTY,null);
public static final LearnStatus NO_QUERY_LEARNED = new LearnStatus(Type.NO_QUERY_LEARNED,null);
public final Exception exception;
private LearnStatus(Type type, Exception exception) {this.type=type;this.exception = exception;}
public static LearnStatus exceptionStatus(Exception cause)
{
if (cause == null) throw new NullPointerException();
return new LearnStatus(Type.EXCEPTION,cause);
}
#Override public String toString()
{
switch(type)
{
case OK: return "OK";
case TIMEOUT: return "timeout";
case NO_TEMPLATE_FOUND: return "no template found";
case QUERY_RESULT_EMPTY:return "query result empty";
case NO_QUERY_LEARNED: return "no query learned";
case EXCEPTION: return "<summary>Exception: <details>"+exception.getLocalizedMessage()+"</details></summary>";
default: throw new RuntimeException("switch type not handled");
}
}
}
I would use an Exception unless everything is OK.
Like
System.out.println("Everything OK!");
} catch(TimeoutException te) {
System.out.println("Timeout :-(")
} catch(Exception e) {
System.out.println("We have an exception: " + e);
}
I don't see any need to use an enum when Exceptions are designed to do this sort of thing.
Adding yet another layer on top of the layer between you and the original exception you can do this.
interface Status {
String getMessage();
}
enum Statuses implements Status {
OK("Everything OK"), TIMEOUT("Timeout :-(");
private final String message;
private Statuses(String message) { this.message = message; }
String getMessage() { return message; }
}
class ExceptionStatus implement Status {
private final String message;
String getMessage() { return "Exception: " + message; }
}
// to print the message
System.out.println(status.getMessage());
There are several approaches to this, but all of them depend that you don't use Enums or that you don't use them exclusively. Keep in mind that an enum is basically a class that only has well-defined singletons as value.
One possible refactoring of this is to use a normal class with well-defined singletons instead of enums:
class Status implements Serializable {
// for serialization
private enum InternalStatus {
OK, TIMEOUT, EXCEPTION
}
public static final Status OK = new Status(null, InternalStatus.OK);
public static final Status TIMEOUT = new Status(null, InternalStatus.TIMEOUT);
private final Exception exception;
private final InternalStatus internalStatus;
private Status(Exception exception, InternalStatus internalStatus) {
this.exception = exception;
this.internalStatus = internalStatus;
}
public Exception getException() {
return exception;
}
public static Status exceptionStatus(Exception cause) {
if (cause == null) throw new NullPointerException();
return new Status(cause, InternalStatus.EXCEPTION);
}
// deserialization logic handling OK and TIMEOUT being singletons
private final Object readResolve() {
switch (internalStatus) {
case InternalStatus.OK:
return OK;
case InternalStatus.TIMEOUT:
return TIMEOUT;
default:
return this;
}
}
}
You can now check for status == Status.OK and status == Status.TIMEOUT. If your status variable is neither OK nor TIMEOUT, it must be caused by an exception, which you can retrieve via getException.
As a downside, you lose the switch functionality and must check via if.

Categories

Resources