How the swagger works in java backend? [closed] - java

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 months ago.
Improve this question
I am a frontend developer. The backend developer left his job. So, I will also work on the backend part. I do not have any experience in the backend development. I am analyzing the backend code. I have few questions. I would like to clear my concepts.
I have attached the Java code file.
1- What are these imports for?:
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
2- why we put #JsonProperty before declaring each variable?
3- why we put class name in few methods? such as:
public LedgerAccountRequestDto taxRateId(String taxRateId) {
this.taxRateId = taxRateId;
return this;
}
4- What is the use of:
#ApiModel(description = "transaction request")
#Validated**
5- What is the use of:
#ApiModelProperty(required = true, value = "")
#NotNull
6- What is hashCode() method actually doing?
public int hashCode() {
return Objects.hash(name, number, typeId, taxRateId);
}
Please help me in understanding these concepts. Thank you very much
package com.kin.account.api.ledgerAccount.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.springframework.validation.annotation.Validated;
import javax.validation.constraints.NotNull;
import java.util.Objects;
/**
* transaction request
*/
#ApiModel(description = "transaction request")
#Validated
public class LedgerAccountRequestDto {
#JsonProperty("name")
private String name = null;
#JsonProperty("number")
private String number = null;
#JsonProperty("typeId")
private String typeId = null;
#JsonProperty("taxRateId")
private String taxRateId = null;
public LedgerAccountRequestDto name(String name) {
this.name = name;
return this;
}
/**
* Get name
* #return name
**/
#ApiModelProperty(required = true, value = "")
#NotNull
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public LedgerAccountRequestDto number(String number) {
this.number = number;
return this;
}
/**
* Get number
* #return number
**/
#ApiModelProperty(required = true, value = "")
#NotNull
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public LedgerAccountRequestDto typeId(String typeId) {
this.typeId = typeId;
return this;
}
/**
* Get typeId
* #return typeId
**/
#ApiModelProperty(required = true, value = "")
#NotNull
public String getTypeId() {
return typeId;
}
public void setTypeId(String typeId) {
this.typeId = typeId;
}
public LedgerAccountRequestDto taxRateId(String taxRateId) {
this.taxRateId = taxRateId;
return this;
}
/**
* Get taxRateId
* #return taxRateId
**/
#ApiModelProperty(required = true, value = "")
#NotNull
public String getTaxRateId() {
return taxRateId;
}
public void setTaxRateId(String taxRateId) {
this.taxRateId = taxRateId;
}
#Override
public boolean equals(java.lang.Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
LedgerAccountRequestDto ledgerAccountRequestDto = (LedgerAccountRequestDto) o;
return Objects.equals(this.name, ledgerAccountRequestDto.name) &&
Objects.equals(this.number, ledgerAccountRequestDto.number) &&
Objects.equals(this.typeId, ledgerAccountRequestDto.typeId) &&
Objects.equals(this.taxRateId, ledgerAccountRequestDto.taxRateId);
}
#Override
public int hashCode() {
return Objects.hash(name, number, typeId, taxRateId);
}
#Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("class LedgerAccountRequestDto {\n");
sb.append(" name: ").append(toIndentedString(name)).append("\n");
sb.append(" number: ").append(toIndentedString(number)).append("\n");
sb.append(" typeId: ").append(toIndentedString(typeId)).append("\n");
sb.append(" taxRateId: ").append(toIndentedString(taxRateId)).append("\n");
sb.append("}");
return sb.toString();
}
/**
* Convert the given object to string with each line indented by 4 spaces
* (except the first line).
*/
private String toIndentedString(java.lang.Object o) {
if (o == null) {
return "null";
}
return o.toString().replace("\n", "\n ");
}
}

I will try to make this very simple and take you step by step
1. What are these imports for?:
import com.fasterxml.jackson.annotation.JsonProperty;
To import java package into a class, we need to use java import keyword which is used to access package and its classes into the java program. Use import to access built-in and user-defined packages into your java source file so that your class can refer to a class that is in another package by directly using its name. So using the above example import com.fasterxml.jackson.annotation.JsonProperty, that line imports the JsonProperty annotation from the jackson library.
2 Why use #JsonProperty before declaring each variable?
#JsonProperty
The #JsonProperty annotation is used to map property names with JSON keys during serialization and deserialization. By default, if you try to serialize a POJO, the generated JSON will have keys mapped to the fields of the POJO. If you want to override this behavior, you can use the #JsonProperty annotation on the fields. It takes a String attribute that specifies the name that should be mapped to the field during serialization.
3 Why we use class names in methods? such as:
public LedgerAccountRequestDto taxRateId(String taxRateId) {
this.taxRateId = taxRateId;
return this;
}
The above is a setter method called narrated with type LedgerAccountRequestDto. It's just the same as having a similar example with the type String. In the code above, the method returns the class instance as the return type.
4 What is the use of:
#ApiModel(description = "transaction request")
#Validated**
#ApiModel is a Swagger annotation.
Swagger is the standard way of documenting the Standard APIs. Swagger is helpful when deploying APIs in azure. Swagger is primarily used for documenting API. for the other developers to be able to use the API, the API must be properly documented; otherwise, how would they know that what are the endpoints exposed by the api and what are the operations supported on those endpoints? What parameters should they pass, and what will they get back? What authentication methods to use?. To answer these questions, it is very important to document the APIs; if you want APIs to be consumed and properly used. To learn more about Swagger, check Swagger - Javatpoint and Swagger - Github repo
#ApiModel - Provides additional information about Swagger models. Swagger-core builds the model definitions based on the references to them throughout the API introspection. The #ApiModel allows you to manipulate the metadata of a model from a simple description or name change to a definition of polymorphism.
#Valid and #Validated Annotations - In Spring, we use JSR-303's #Valid annotation for method level validation. We also use it to mark a member attribute for validation. However, this annotation doesn't support group validation.
Groups help to limit the constraints applied during validation. One particular use case is UI wizards. In the first step, we may have a certain sub-group of fields. In the subsequent step, there may be another group belonging to the same bean. So we need to apply constraints on these limited fields in each step, but #Valid doesn't support this.
In this case, for group-level, we have to use Spring's #Validated, which is a variant of JSR-303's #Valid. This is used at the method level. For marking member attributes, we continue to use the #Valid annotation.
5 What is the use of:
#ApiModelProperty(required = true, value = "")
#NotNull
#ApiModelProperty - In Swagger, this Adds and manipulates data of a model property. The #ApiModelProperty allows controlling Swagger-specific definitions such as allowed values, and additional notes. It also offers additional filtering properties in case you want to hide the property in certain scenarios.
The required parameter specifies if the parameter is required or not. The value parameter defines a brief description of this property.
The #NonNull is a common Spring annotation to declare that annotated elements cannot be null. It denotes that a parameter, field, or method return value can never be null. This is a marker annotation and it has no specific attributes.
6 What is hashCode() method actually doing?
public int hashCode() {
return Objects.hash(name, number, typeId, taxRateId);
}
The hashCode method is an inbuilt method that returns the integer hashed value of the input value. To properly understand hashCode() and equals() using examples, check out HashCode() in Java - scaler.com and also What is the hashCode method in Java? - educative.io
ADVICE
You have to learn Java if you don't have the basics, researching this way will be so difficult. Check the below resource links to learn Java and Spring boot.
Learn Java
Notes - Learn Java - By Jakob Jenkov
Videos - Learn Java - By Java Guides
Learn Spring Boot
Notes - Learn SpringBoot - By Javatpoint
Videos - Learn SpringBoot - By Java Guides

Related

Java JAXB marshall/unmarshall using Java Optionals

My applications needs to convert data between Java and XML.
When converting the data, I need to distinguish whether or not the value was present, the value was set explicitly to null or the value had a value.
XML example:
<person><name>Bob</name></person> <-- element 'name' contains value "Bob"
<person><name nil="true"/></person> <-- element 'name' was set explicitly to 'nil'/null
<person></person> <-- element 'name' is missing
As Java types like 'String' only knows two states (null or not null), I tried to use Java Optionals to solve this.
A mapping between XML and Java Optionals could look like this:
<person></person> <=> Optional<String> name = null;
<person><name>Bob</name></person> <=> Optional<String> name = Optional.of("Bob");
<person><name nil="true"/></person> <=> Optional<String> name = Optional.empty();
I tried to use JAXB for the marshalling and unmarshalling. The idea was that the setter of a field only gets invoked when a value needs to be set explicitly to an value. That means that a value is absent implicitly.
I had a look on other stackoverflow questions like the following, but all of them were incomplete handling the behaviour I need to achieve:
How to generate JaxB-Classes with java.util.Optional?
Using generic #XmlJavaTypeAdapter to unmarshal wrapped in Guava's Optional
Using Guava's Optional with #XmlAttribute
I've been struggling with this problem for two days now. I tried to use the XMLAdapter and GenericAdapter, tried several ways how to annotate the fields and getter/setter with #XmlElement, tried to use #XmlAnyElment with and without lax, but all of them only led to a partial success. Either the nil value was not handeld correctly, the lists were not printed out correctly, ...
I think every Java webservice with a properly implemented patch operation should have had this problem. (not talking about the "json patch approach" (RFC 6902))
Is there a common way to solve my problem?
The following code is able to distinguish empty name from null name. To make the solution work, I created a PersonList element to contain all of the person elements. Each Person contains a Name that will have isNil() return true if the element was explicitly set to null by the XML:
Person.java:
import java.util.Optional;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
#XmlType(propOrder = {"name"})
#XmlRootElement(name = "person")
public class Person {
private Optional<Name> optionalName;
public Person() {
optionalName = Optional.<Name>empty();
}
public Optional<Name> getOptionalName() {
return optionalName;
}
public Name getName() {
return (optionalName.isPresent()) ? (optionalName.get()) : (null);
}
#XmlElement(name = "name", required = false)
public void setName(Name name) {
optionalName = Optional.ofNullable(name);
}
#Override
public String toString() {
return String.format("Person(optionalName.isPresent() = %s, name = %s)",
Boolean.toString(optionalName.isPresent()),
((getName() == null) ? ("null") : (getName().toString())));
}
}
Name.java:
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlValue;
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name = "name")
public class Name {
#XmlAttribute(name = "nil")
private boolean nil;
#XmlValue
private String value;
public Name() {
nil = false;
value = null;
}
public boolean isNil() {
return nil;
}
public void setNil(boolean torf) {
this.nil = torf;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
#Override
public String toString() {
return String.format("Name(nil = %s, value = %s)",
Boolean.toString(nil),
(value == null) ? ("null"):("\""+getValue()+"\""));
}
}
PersonList.java:
import java.util.Iterator;
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name = "PersonList")
public class PersonList {
private List<Person> persons;
public PersonList() {
persons = null;
}
#XmlElement(name = "person")
public List<Person> getPersons() {
return persons;
}
public void setPersons(List<Person> persons) {
this.persons = persons;
}
#Override
public String toString() {
StringBuilder sb = new StringBuilder("PersonList(persons = ");
if(persons == null) {
sb.append("null");
}
else {
sb.append("[");
Iterator<Person> iterator = persons.iterator();
while(iterator.hasNext()) {
sb.append(iterator.next().toString());
if(iterator.hasNext()) {
sb.append(", ");
}
}
sb.append("]");
}
sb.append(")");
return sb.toString();
}
}
Main class to demonstrate the solution:
import java.io.ByteArrayInputStream;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
public class XmlOptional {
public static final int STATUS_OKAY = 0;
public static final int STATUS_ERROR = -1;
public static final String XML_DATA = "<PersonList>" +
"<person><name>Bob</name></person>" +
"<person><name nil=\"true\" /></person>" +
"<person></person>" +
"</PersonList>";
private XmlOptional() {
}
private static PersonList loadXml() {
try {
ByteArrayInputStream bais = new ByteArrayInputStream(XML_DATA.getBytes());
JAXBContext context = JAXBContext.newInstance(PersonList.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
PersonList personList = (PersonList)unmarshaller.unmarshal(bais);
return personList;
}
catch(Exception e) {
throw new RuntimeException(e);
}
}
public static void main(String[] args) {
int status = STATUS_OKAY;
try {
PersonList personList = loadXml();
System.out.format("Xml contained: %s%n", personList);
}
catch (Throwable thrown) {
status = STATUS_ERROR;
thrown.printStackTrace();
}
finally {
System.exit(status);
}
}
}
Sample output:
Xml contained: PersonList(persons = [Person(optionalName.isPresent() = true, name = Name(nil = false, value = "Bob")), Person(optionalName.isPresent() = true, name = Name(nil = true, value = "")), Person(optionalName.isPresent() = false, name = null)])
Since I was not able to solve the problem completely by solely using and configuring JAXB properly, I decided to solve it as follows:
(The main goal was to write a subsystem to communicate with an external system based on XML)
As a starting point, I used the XSD schema provided by the target system to communicate with and generated the corresponding (XML)Java classes using JAXB and the XSD file. All the fields in those generated classes were of type JAXBElement<>, in order to be able to hold the 3 states needed (absent, null, someValue).
On the business model side, I used Java classes with Optional<> field types in order to hold the 3 states.
For the mapping, I wrote a mapper which uses reflection to recursively map from JAXB to Java and vice versa. When mapping from Java to JAXB, the mapper used the ObjectFactory to create the JAXBElement objects. (Mapper itself just had about 300 lines of code).
The fields were mapped based on the matching field names.
The most ugly and challenging part was, that the XSD schema file needed to be altered, in order to make JAXB generated classes that uses JAXBElement field types. Therefore I had to manually add the attribute minOccurs="0" nillable="true" to the XML elements, if not already set.
With that solution above, I finally managed to map the XML to Java and vice versa considering the 3 states needed, easily.
Of course, this solution has its drawbacks.
One is the manual modification of the XSD file. Usually bad practice to alter the XSD file provided by the external system, which acts as an interface contract.
For my requirements at the time, the solution worked perfectly. Even changes to the interface contract of the external system could be implemented very easily.
You can use some validation in your java class like #NotNull, #Size and so on. Or you can put default value , to be sure , that it will be not null. After that you can create DTOs (Data transfer object) with the recommended Xml annotations and mapped it with the ModelMapper.

What to do with a class where one particular variable is sometimes not used

Beginner question here. I'm writing a Java program that queries a public API on the internet to retrieve details of discussions on a forum. The data comes back as JSON and I'm parsing that into Java objects to be used in my program.
A discussion normally contains five attributes, i.e. the five public variables. However, in response to a limited number of specific search types, the number of comments is not returned.
Is there a 'best' (in terms of object oriented programming) way to deal with this sort of scenario? My first attempt is below, where I have simply written two constructors, one that assigns a value to numberOfComments, and one that does not.
This doesn't seem like a great solution - what happens if another class creates a DiscussionDetails object, uses the constructor that does not populate numberOfComments, but then later tries to use the numberOfComments field?
I thought that maybe it should be split into two classes, where DiscussionDetails has no numberOfComments field, and DiscussionDetailsSpecialised is a subclass with an additional numberOfComments field. This feels a bit like overkill to me, for the sake of one single field.
Or maybe there's a convention that such a variable is initialised with a particular value like 'false' or '-1' or something?
Are there other, better approaches that an experienced programmer would use for this kind of situation?
I know the example is trivial, but I'm using it to try to illustrate my question as simply as possible.
/**
* Wrapper for a set of JSON data returned from an API
*/
public class DiscussionDetails
{
public String discussionID;
public String discussionName;
public String discussionURL;
public String submittedDate;
public String numberOfComments;
/**
* Constructor that populates all fields
*/
public DiscussionDetails(String discussionID, String discussionName, String discussionURL, String submittedDate, String numberOfComments)
{
this.discussionID = discussionID;
this.discussionName = discussionName;
this.discussionURL = discussionURL;
this.submittedDate = submittedDate;
this.numberOfComments = numberOfComments;
}
/**
* Constructor method to use when the number of comments is unknown, which happens in certain specific cases
*/
public DiscussionDetails(String discussionID, String discussionName, String discussionURL, String submittedDate)
{
this.discussionID = discussionID;
this.discussionName = discussionName;
this.discussionURL = discussionURL;
this.submittedDate = submittedDate;
}
}
This has been traditionally solved with "special" values (values that obviously make no sense, eg: -1 for a count) or null (which in a sense is the most special value).
The "best" way to deal with this is, IMHO, java.util.Optional: clients have to check if a value is present when they wish to use it and Optional makes this explicit, avoiding the common source of bugs of a client forgetting to check.
One way to solve this is with a builder. Your example is good, but a builder can help make it more obvious what's going on.
/**
* Wrapper for a set of JSON data returned from an API
*/
public class DiscussionDetails
{
public String discussionID;
public String discussionName;
public String discussionURL;
public String submittedDate;
public String numberOfComments;
public static class Builder{
private DiscussionDetails dd = new DiscussionDetails();
public discussionID(String discussionID) {
dd.discussionID = discussionID;
return this;
}
public discussionName(String discussionName) {
dd.discussionName= discussionName;
return this;
}
public discussionURL(String discussionURL) {
dd.discussionURL= discussionURL;
return this;
}
public submittedDate(String submittedDate) {
dd.submittedDate= submittedDate;
return this;
}
public numberOfComments(String numberOfComments) {
dd.numberOfComments= numberOfComments;
return this;
}
public DiscussionDetails build() {
return dd;
}
}
}
This can make your instantiation a little cleaner, especially with optional fields or a lot of fields.
You would use this like:
DiscussionDetails details =
new DiscussionDetails.Builder()
.discussionID("1")
.discussionName("Name")
.build();
In this particular case, I've set 2 of the fields. The other fields would be null, or the default value. With some extra code, this gives you a lot of flexibility and arguably makes the code easier to read.
If you need to enforce certain fields being set, you can add more methods in the Builder class itself, or throw an error from the build method.
The "special" value for handling a case when there is no value for a given property is a null value (nil in some languages). However, you should document this in your code so that the client of the code knows that the numberOfComments can be null - forgetting about it and trying to use the value ends with one of the most common exceptions - NullPointerException.
call this in your constructor
public class DiscussionDetails {
public String discussionID;
public String discussionName;
public String discussionURL;
public String submittedDate;
public String numberOfComments;
/**
* Constructor that populates all fields
*/
public DiscussionDetails(String discussionID, String discussionName, String discussionURL,
String submittedDate, String numberOfComments) {
this(discussionID, discussionName, discussionURL, submittedDate);
this.numberOfComments = numberOfComments;
}
/**
* Constructor method to use when the number of comments is unknown, which happens in certain
* specific cases
*/
public DiscussionDetails(String discussionID, String discussionName, String discussionURL,
String submittedDate) {
this.discussionID = discussionID;
this.discussionName = discussionName;
this.discussionURL = discussionURL;
this.submittedDate = submittedDate;
}
}

Play framework 2 (Java) form data binding with nested allowed fields

Consider following model:
public class Contact {
#Required
public String name;
#Valid
public List<Information> informations;
}
public static class Information {
public String securedField;
#Required
public String email;
#Valid
public List<Phone> phones;
public static class Phone {
#Required
#Pattern(value = "[0-9.+]+", message = "A valid phone number is required")
public String number;
}
}
}
I don't want Information securedField to be affected by mass assignment vulnerability. So i decided to set array of allowedFields for Contact Form.
As i know, play forms are based on Spring DataBinder, so is it possible to handle collection fields? I don't want to write smth like:
name
informations[0].email
informations[0].phones*
informations[1].email
informations[1].phones*
etc
Following doesn't work:
name
informations.email
informations.phones*
Should i extend existing Spring DataBinder and Form classes and override bind method in this case?
Here's an arguably simpler solution. How about defining an extra constraint that will trigger a validation failure if the POST data contains any informations[%d].securedField values?
import javax.validation.constraints.Null;
public static class Information {
#Null
public String securedField;
...
}
I think that this way you can call the default bindFromRequest method instead of the one that accepts a whitelist of form field names, and still be protected against a mass assignment attack.
One shortcoming with this approach admittedly is that it would ultimately leak the names of your internal fields in the event of a concerted mass assignment attack. However if they had fairly bland, meaningless names such as securedField (no offence intended!), I'm not sure how this information could be exploited by an attacker.
Edit
If you want to allow assignment to the field based on the current user type, maybe bean validation groups could help:
import javax.validation.constraints.Null;
public class Contact {
public interface Administrator {}
public interface User {}
...
public class Information {
#Null(groups = User.class)
public String securedField;
...
}
}
Controller code
...
final Form<Contact> contactForm;
if (currentUser.isAdministrator()) {
contactForm = form(Contact.class, Administrator.class).bindFromRequest();
} else {
contactForm = form(Contact.class, User.class).bindFromRequest();
}
...
If I understand your question correctly, you can use the following patterns to whitelist nested collection fields:
informations[*].email
informations[*].phones[*].*
i.e.
form.bindFromRequest("name", "informations[*].email", "informations[*].phones[*].*");

My custom accessor is never used and only the field default value is used by hibernate validator instead

I have the following code inside a javabean:
#AssertTrue
private boolean addressReferenceValid;
public boolean isAddressReferenceValid() {
if (addressType.equals(AddressType.ON_THE_FLY_ADDRESS) && StringUtils.isEmpty(addressReference)) {
return false;
}
return true;
}
The issue I have is that the isAddressReferenceValid accessor is never used and it seems that only the default value for addressReferenceValid is used (i.e. false).
I have double checked that Spring Roo did not generate its own accessor for that variable.
Can anyone please help?
P.S. I can't put the #AssertTrue annotation directly on the method because then the following key in ValidationMessages.properties file would not be resolved: AssertTrue.familyAdvertisementSearchCriteriaInfo.addressReferenceValid
edit 1:
Full bean:
#RooEquals
#RooJavaBean
public class FamilyAdvertisementSearchCriteriaInfo {
#Valid
private FamilyAdvertisementSearchCriteria searchCriteria;
private Address currentAddress;
private String addressReference;
#NotNull
private AddressType addressType;
#AssertTrue(groups=Default.class)
private boolean addressReferenceValid;
public boolean isAddressReferenceValid() {
if (addressType.equals(AddressType.ON_THE_FLY_ADDRESS) && StringUtils.isEmpty(addressReference)) {
return false;
}
return true;
}
}
Validation occurs in the following controller:
#RequestMapping(value = "/familyAdvertisementSearch", method = RequestMethod.POST, produces = "text/html")
public String familyAdvertisementSearchResults(#ModelAttribute #Validated(Default.class) FamilyAdvertisementSearchCriteriaInfo familyAdvertisementSearchCriteriaInfo, BindingResult bindingResult, Model model) {
if(bindingResult.hasErrors()){
populateModel(model);
familyAdvertisementSearchCriteriaInfo.setCurrentAddress(memberService.retrieveCurrentMemberAddress());
return "search/familyAdvertisementSearchForm";
}
...
I think I understand now what you are trying to do. You want to place the constraint on the field, but during validation you expect the method isAddressReferenceValid to be called/used. That's not going to work. If you place a constraint on a field access is used to get the property to validate (using reflection). If you place it on a method/getter method access is used. So he placement of the annotation matters. As you already seem to have discovered placing the annotation on the method works. Of course this leads to inconsistent placement of annotations. You could:
Just place the annotation for this single constraint
switch to method annotations completely
update the Boolean every time the address type changes (and get rid of isAddressReferenceType method)
create a custom constraint for verifying the addressReference
Just some ideas. It all depends on your use case and personal preferences.

How to make BlazeDS ignore properties?

I have a java class which has one field with getter and setter, and a second pair of getter and setter that access this field in another way:
public class NullAbleId {
private static final int NULL_ID = -1;
private int internalId;
getter & setter for internalId
public Integer getId() {
if(this.internalId == NULL_ID) {
return null;
} else {
return Integer.valueOf(internalId);
}
}
public void setId(Integer id) {
if (id == null) {
this.internalId = NULL_ID;
} else {
this.internalId = id.intValue();
}
}
}
(the reason for this construction is that I want to build a way to hande Nullable Intergers)
On the Flash/Flex client side, I have a Class with two properties: id and internalId (the id properties are only for testing, at the end they should return the internalId value)
BlazeDS seams to transfer both values: id and internalId, because both have a complete getter setter pair. I want Blaze not to transfer id, only internalId should be transferred. But I have no idea how I have to configure that.
All the rules for BlazeDS serialization are here:
http://livedocs.adobe.com/blazeds/1/blazeds_devguide/help.html?content=serialize_data_3.html
Here is a quote: "Fields that are static, transient, or nonpublic, as well as bean properties that are nonpublic or static, are excluded."
So if you can make your id property fit that criteria it will be excluded. Another option would be to create a custom serializer that overtly does not include your id property.
All the best,
~harris
Besides transient / marshaller you can implement the Externalizable interface and create your custom serialization.
See serialization rules
It maybe a little bit old, but it could help some : there is a nice ticket about excluding properties from Java to Flex via BlazeDS
EDIT : a better soluce, it's to use the #AmfIgnore (or #AmfIgnoreField if your serialization is directly on the fields) annotation present in the spring-flex-core.jar (I've used the 1.5.2-RELEASE)

Categories