What is the purpose of using #PortableProperty - java

I recently came across a part of code which has annotation #PortableProperty used for variables declared in a DTO. Can anyone please explain what it does and the need for using it?

Portable marks a class as being eligible for use by a PofAnnotationSerializer. This annotation is only permitted at the class level and is a marker annotation with no members. The following class illustrates how to use Portable and PortableProperty annotations.
A PortableProperty marks a member variable or method accessor as a POF serialized attribute. Whilst the value() and codec() can be explicitly specified they can be determined by classes that use this annotation. Hence these attributes serve as hints to the underlying parser.
Quoted this from doc found here and here. Check this for more details.
Example:
public class Book
extends ExternalIdEntity
implements Serializable, PortableObject {
#PortableProperty(1)
private String id;
#PortableProperty(3)
private String parentId;
#PortableProperty(4)
private String name;
#PortableProperty(5)
private String legalEntityId;
...
}

Related

#JsonView: different perspectives

I'm coding a Spring Web Service, using Jackson by default. I'm using #JsonView to indicate which property I need to be parsed to my JSON object. So, the problem is: Many objects are used in different classes, but not exactly all its properties, for example:
class Professor {
#JsonView({Views.Public.class, Views.Internal.class})
private int id;
#JsonView(Views.Internal.class)
private String name;
...
}
class Classroom {
#JsonView({Views.Public.class, Views.Internal.class})
private int id;
#JsonView(Views.Internal.class)
private String name;
...
}
class Lecture {
#JsonView(Views.Public.class)
private Professor professor;
#JsonView(Views.Public.class)
private Classroom classroom;
...
}
What if I need more than two 'perspectives', I'd have to create more interfaces/classes to do that? (like Views.Professor, Views.Principal, ...) Is this a real good practice?
I'd like to hear some suggestions or alternatives to solve that. I'm a little bit confused about being on the right track.
Generic names
You always can define more views if you need more perspectives, that's the idea behind the Jackson JSON views and that's what makes it flexible.
If you use generic names in your views classes, such as Basic, Extended, Public, Private and so on, you'll find it easier to reuse them across multiple beans.
Inheritance
You always can rely on inheritance with #JsonView. Consider the following example where Views.Private extends Views.Public:
public class Views {
interface Public {}
interface Private extends Public {}
}
Serialization of properties annotated with #JsonView(Views.Private.class) will also include properties annotated with #JsonView(Views.Public.class).

Java entity - why do I need an empty constructor?

This might sound stupid to you,
but why do I need to define an empty constructor in my #Entitys?
Every tutorial I saw said : every entity needs an empty constructor.
But Java always give you a default invisible empty constructor (if you don't redefine one).
Let me clarify..
What I understood by "need" was write.
Meaning: always write an empty constructor in your entity.
example:
#Entity
public class MyEntity implements Serializable {
#Id
private String str;
public MyEntity(){}
//here getter and setter
}
But Java always gives you this empty constructor when you don't redefine it (write an other one with parameters).
In this case writing this empty constructor seems useless.
An empty constructor is needed to create a new instance via reflection by your persistence framework. If you don't provide any additional constructors with arguments for the class, you don't need to provide an empty constructor because you get one per default.
You can also use the #PersistenceConstructor annotation which looks like following
#PersistenceConstructor
public Movie(Long id) {
this.id = id;
}
to initialise your entity if Spring Data is present in your project. Thus you can avoid the empty constructor as well.
But java always give you a default invisible empty constructor (if you
don't redefine one).
This statement is true only when you don't provide any constructor in your class. If an argument constructor is provided in your class, then JVM will not add the no-argument constructor.
Explicitly defining a default constructor is not necessary unless you provide another constructor for the entity. If you provide another constructor, aside from one with the default constructor's signature, the default constructor will not be created.
Since JPA implementations rely upon the existence of a default constructor it is then necessary to include the default constructor that will be omitted.
As you specified the "JPA" tag, I assume your question applies to JPA only and not empty constructors in general.
Persitence frameworks often use reflection and more specifically Class<T>.newInstance() to instantiate your objects, then call getters/setters by introspection to set the fields.
That is why you need an empty constructor and getters/setters.
See this StackOverflow question about empty constructors in Hibernate.
Actually you don't need to write it. You have it by default. Sometimes you can create private constructor to prevent users to use default
public class MyClass{
private MyClass(){}
}
For singelton patterns, for example you can block using default constructor.
Sometimes, when you use Gson plugin to convert String Json data to Object, it demands to write default constructor, otherwise it doesn't work
All the answers are fine.
But let's talk with code. Following snippets of code will give you more clarity.
PersonWithImplicitConstructor.java
public class PersonWithImplicitConstructor {
private int id;
private String name;
}
First we have to compile the .java file
javac PersonWithImplicitConstructor.java
Then class file will be generated.
Running the javap on top this class file will give you the following information.
javap PersonWithImplicitConstructor.class
Compiled from "PersonWithImplicitConstructor.java"
public class PersonWithImplicitConstructor {
public PersonWithImplicitConstructor();
}
NOTE: If you want more information, you can use -p flag on javap.
The next java file will have parameterised constructor only.
PersonWithExplicitConstructor.java
public class PersonWithExplicitConstructor {
private int id;
private String name;
public PersonWithExplicitConstructor(int id, String name) {
this.id = id;
this.name = name;
}
}
javac PersonWithExplicitConstructor.java
javap PersonWithExplicitConstructor.class
Compiled from "PersonWithExplicitConstructor.java"
public class PersonWithExplicitConstructor {
public PersonWithExplicitConstructor(int, java.lang.String);
}
PersonWithBothConstructors.java
public class PersonWithBothConstructors {
private int id;
private String name;
public PersonWithBothConstructors() {
}
public PersonWithBothConstructors(int id, String name) {
this.id = id;
this.name = name;
}
}
javac PersonWithBothConstructors.java
javap PersonWithBothConstructors.class
Compiled from "PersonWithBothConstructors.java"
public class PersonWithBothConstructors {
public PersonWithBothConstructors();
public PersonWithBothConstructors(int, java.lang.String);
}
Java not always give you a default invisible empty constructor if your class got argument constructor, you have to define the empty constructor by your own.
From the JPA tag, I suppose that you are working with Java beans. Every bean needs to have the following properties:
Getters and setters for all its main instance variables.
An empty constructor.
All its instance variables should preferably be private.
Thus the statement : "every entity needs an empty constructor".

JavaBean class rules

What are the correct rules to write a JavaBean class?
I'm confused because some books use MUST while other user SHOULD or COULD to describe
the writing rule:
i.e.
a bean class MUST implements Serializable or SHOULD?
the instance variables MUST be private or SHOULD BE?
A JavaBean is defined by its properties (i.e. its getter and setter methods), not it's fields. Although the terms are used interchangably, that is actually not correct. The Introspector mechanism ignores fields completely.
Example
Take this (awfully designed) Javabean:
public class TestBean {
private int baz;
private char[] phleem;
public String getFoo() {
return new String(phleem);
}
public void setFoo(final String foo) {
this.phleem = foo.toCharArray();
}
public long getBar() {
return baz;
}
public void setBar(final long bar) {
this.baz = (int) bar;
}
}
You'd think the properties are:
"baz" (int)
"phleem" (char[])
but now let's inspect it with the Javabeans introspector:
for (PropertyDescriptor descriptor : Introspector
.getBeanInfo(TestBean.class, Object.class)
.getPropertyDescriptors()) {
System.out.println("Name: " + descriptor.getName() +
", type: " + descriptor.getPropertyType());
}
Here's the output:
Name: bar, type: long
Name: foo, type: class java.lang.String
Conclusion:
Getters and setters are what define a Javabeans property. It's a convention that they are backed by fields of the same name and type, but the fields are not actually part of the Javabean properties (although many documentations will suggest otherwise).
On re-reading my answer: it is meant as an addendum to the other answers. If you want a short and simple answer, go with skaffman's.
It is a public class.
It has a public parameterless constructor (though it may have other constructors
as well)
It implements Serializable interface (i.e. it can be made persistent, so its state can
be saved)
It has properties with “getter” and “setter” methods named by following
JavaBeans naming patterns
It has events which follow the standard Java event model with the registration
methods named by following the JavaBeans naming patterns
It may have other methods which do not follow the naming patterns. These
methods are not exposed by a builder tool.
Adding to the previous poster - skaffman. It is always a good practice to override, toString(), hashCode(), equals() and finally write a overloaded constructor that has all the fields (that this class has) as input.
Be sure not to use other references (like List, HashMaps etc) in the toString() and hashCode()'s implementation.
On a side note, eclipse has built-in functionality to generate them for you..
A Java Bean is a Java class that should follow the following conventions:
It should have a no-arg constructor.
It should be Serializable.
It should provide methods to set and get the values of the properties, known as getter and setter methods.
All the above and it should not cross the boundaries of Java API . It means it should not extend or implement any classes or interface,but one relaxation is there it can implement only one serializable interfce why because it is a marker interface

Problems with GWT and Enum

I have an enum in the client part of a GWT application and I am getting an exception when I try to run it that is related to serialization problems. Am I doing anything wrong? I read that enums are supported by GWT and I am using the last version.
The enum:
public enum AnEnum implements Serializable {
ITEM_A("Item a description"), ITEM_B("Item b description");
private String description;
private AnEnum(String description) {
this.description = description;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
The exception:
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter.serializeWithCustomSerializer(ServerSerializationStreamWriter.java:742)
... 47 more
Caused by: com.google.gwt.user.client.rpc.SerializationException: Type '(...).client.(...).AnEnum' was not included in the set of types which can be serialized by this SerializationPolicy or its Class object could not be loaded. For security purposes, this type will not be serialized.: instance = ITEM_A
at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter.serialize(ServerSerializationStreamWriter.java:610)
at com.google.gwt.user.client.rpc.impl.AbstractSerializationStreamWriter.writeObject(AbstractSerializationStreamWriter.java:129)
at com.google.gwt.user.client.rpc.core.java.util.Collection_CustomFieldSerializerBase.serialize(Collection_CustomFieldSerializerBase.java:43)
at com.google.gwt.user.client.rpc.core.java.util.LinkedList_CustomFieldSerializer.serialize(LinkedList_CustomFieldSerializer.java:36)
... 52 more
Add IsSerializable interface, a default scoped no-arg constructor, and make sure its in one of the paths listed in the source tags in your gwt.xml file. <source path="client">
I really think the third suggestion is the issue; I remember having this issue before and it was because I had a dto outside the source paths.
You can have multiple source tags.
<source path="common" />
<source path="client" />
One pattern is to put persisted objects directly under com.mysite.common, and mashups of persisted items that get transferred over the wire in com.mysite.common.dto, and of course the client gui code is in client.
package com.mysite.client;
import java.io.Serializable;
import com.google.gwt.user.client.rpc.IsSerializable;
public enum AnEnum implements Serializable, IsSerializable {
ITEM_A("Item a description"), ITEM_B("Item b description");
private String description;
AnEnum() {
}
AnEnum(String description) {
this.description = description;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
You can try this check list:
Verify that the class has a default constructor (without arguments)
Verify that the class implements Serializable or IsSerializable or
implements an Interface that extends Serializable or extends a class
that implement Serializable
Verify that the class is in a client.* package or …
Verify, if the class is not in client.* package, that is compiled in
your GWT xml module definition. By default
is present. If your class is in another package you have to add it
to source. For example if your class is under domain.* you should
add it to xml as . Be aware that the class
cannot belong to server package! More details on GWT page: http://code.google.com/webtoolkit/doc/latest/DevGuideOrganizingProjects.html#DevGuideModuleXml
If you are including the class from another GWT project you have to
add the inherits to your xml module definition. For example if your
class Foo is in the package com.dummy.domain you have to add
to the module definition.
More details here: http://code.google.com/webtoolkit/doc/latest/DevGuideOrganizingProjects.html#DevGuideInheritingModules
If you are including the class from another GWT project released as
a jar verify that the jar contains also the source code because GWT
recompile also the Java source for the classes passed to the Client.
Font: http://isolasoftware.it/2011/03/22/gwt-serialization-policy-error/
i think you need a no arg constructor.
I been studying above to solve some GWT code written in 2008, when upgraded to GWT SDK 2.4.0 (with latest gxt*.jar) gives me:
[WARN] adempiereService: An IncompatibleRemoteServiceException was thrown while processing this call.
com.google.gwt.user.client.rpc.IncompatibleRemoteServiceException: com.google.gwt.user.client.rpc.SerializationException: Type 'org.idempiere.ui.gwt.client.util.AdempiereGXTUtil$LoginStage' was not included in the set of types which can be deserialized by this SerializationPolicy or its Class object could not be loaded. For security purposes, this type will not be deserialized.
at com.google.gwt.user.server.rpc.RPC.decodeRequest(RPC.java:315)
at com.google.gwt.user.server.rpc.RemoteServiceServlet.processCall(RemoteServiceServlet.java:206)
...
Caused by: com.google.gwt.user.client.rpc.SerializationException: com.google.gwt.user.client.rpc.SerializationException: Type 'org.idempiere.ui.gwt.client.util.AdempiereGXTUtil$LoginStage' was not included in the set of types which can be deserialized by this SerializationPolicy or its Class object could not be loaded. For security purposes, this type will not be deserialized.
at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamReader.deserialize(ServerSerializationStreamReader.java:581)
That notorious class is as follows (edited to follow ideas given in this thread):
public class AdempiereGXTUtil {
public enum LoginStage implements IsSerializable, Serializable {
LOGOUT,
LOGIN,
ISLOGGEDIN,
ROLES,
WRONGUSER,
WRONGROLE;
LoginStage(){
}
};
}
Thinking about Andrej's answer to add type to white-list but enum is not some new myType, right? Anyway here is some reference in the codebase (non-relevant fields removed):
public interface AdempiereService extends RemoteService {
public static final String SERVICE_URI = "adempiereService";
public static class Util {
public static AdempiereServiceAsync getInstance() {
AdempiereServiceAsync instance = (AdempiereServiceAsync) GWT
.create(AdempiereService.class);
return instance;
}
}
...
public LoginStage getLoginStage();
with:
public interface AdempiereServiceAsync {
...
public void getLoginStage(AsyncCallback<LoginStage> callback);
Originally the AdempiereGXTUtil did not implement IsSerializable, Serializable nor has empty constructor but putting them in above, and cleaning out project in Eclipse does not change the same errors. Eclipse version used is Indigo on Java 1.6 in a Mac Lion environment. Hoping to get more from this thread, which by the way is amazing in its technical depth.
Only names of enumeration constants are serialized by GWT's RPC. Field values are not serialized.
GWT:Server Communication:Serializable Types
In this case, Enum cannot be in the class. You have to create an external Enum.
In Gwt 2.9, I also had a "was not included in the set of types which can be serialized" error on a class that contained a field of type java.util.EnumSet of a custom enum class.
It turned out the issue was not my custom enum, but the EnumSet itself. After replacing the EnumSet with a HashSet or LinkedHashSet, serialization worked.
Maybe this is related to this issue: https://github.com/gwtproject/gwt/issues/3319
See http://www.gwtproject.org/doc/latest/DevGuideServerCommunication.html#DevGuideSerializableTypes:
A type is serializable and can be used in a service interface if one
of the following is true:
The type is primitive, such as char, byte, short, int, long, boolean,
float, or double. The type an instance of the String, Date, or a
primitive wrapper such as Character, Byte, Short, Integer, Long,
Boolean, Float, or Double. The type is an enumeration. Enumeration
constants are serialized as a name only; none of the field values are
serialized. The type is an array of serializable types (including
other serializable arrays). The type is a serializable user-defined
class. The type has at least one serializable subclass. The type has a
Custom Field Serializer
In your case the type is an enumeration, so it is meant to be serializable.
These days GWT has 2 serialisation policies: LegacySerializationPolicy and StandardSerializationPolicy.
The LegacySerializationPolicy has an issue serialising enums unless they implement IsSerializable.
Normally StandardSerializationPolicy will be used unless the SerializationPolicyProvider cannot find the *.gwt.rpc file for some reason. If it cannot find the *.gwt.rpc file then it will write a warning that you will most likely get serialisation issues so I would suggest that you start looking in the error log to see if it had issues finding the *.gwt.rpc file and if so fix that.
Also on a side note you should not be mutating Enums, I recall that Joshua Bloch writes about that in his book Effective Java.
a) You definitely need a no-op constructor for serialization.
b) You can either extend GWT' IsSerializable class or, if you want to use Java's Serialization interface you must setup a policy to allow this. There's a post related to this at How do I add a type to GWT's Serialization Policy whitelist?. Also, check the GWT sight for more information on IsSerializable vs. Serializable.

Marshalling polymorphic objects in JAX-WS

I'm creating a JAX-WS type webservice, with operations that return an object WebServiceReply. The class WebServiceReply itself contains a field of type Object. The individual operations would populate that field with a few different data-types, depending on the operation.
Publishing the WSDL (I'm using Netbeans 6.7), and getting a ASP.NET application to retrieve and parse the WSDL was fine, but when I tried to call an operation, I would receive the following exception:
javax.xml.ws.WebServiceException: javax.xml.bind.MarshalException
- with linked exception:
[javax.xml.bind.JAXBException: class [LDataObject.Patient; nor any of its super class is known to this context.]
How do I mark the annotations in the DataObject.Patient class, as well as the WebServiceReply class to get it to work? I haven't been able to fine a definitive resource on marshalling based upon annotations within the target classes either, so it would be great if anybody could point me to that too.
WebServiceReply.java
#XmlRootElement(name="WebServiceReply")
public class WebServiceReply {
private Object returnedObject;
private String returnedType;
private String message;
private String errorMessage;
.......... // Getters and setters follow
}
DataObject.Patient.java
#XmlRootElement(name="Patient")
public class Patient {
private int uid;
private Date versionDateTime;
private String name;
private String identityNumber;
private List<Address> addressList;
private List<ContactNumber> contactNumberList;
private List<Appointment> appointmentList;
private List<Case> caseList;
}
Solution
(Thanks to Gregory Mostizky for his answer)
I edited the WebServiceReply class so that all the possible return objects extend from a new class ReturnValueBase, and added the annotations using #XmlSeeAlso to ReturnValueBase. JAXB worked properly after that!
Nonetheless, I'm still learning about JAXB marshalling in JAX-WS, so it would be great if anyone can still post any tutorial on this.
Gregory: you might want to add-on to your answer that the return objects need to sub-class from ReturnValueBase. Thanks a lot for your help! I had been going bonkers over this problem for so long!
You need to use #XmlSeeAlso so that your JAXB implementation will now to include additional classes as well.
In your case it would go something like this:
#XmlRootElement
#XmlSeeAlso({Patient.class, ....})
public class ReturnValueBase {
}
And also change returnedObject property to be of type ReturnValueBase.

Categories

Resources