I am trying to use GWTs RequestFactory to (at the moment) do something very simple and return a list of objects each containing some data and another object. I don't seem to be able to get my other object - instead I always get null.
My code looks something like this...
I have some UserMessage objects which each include a Message object.
UserMessage
#Entity
public class UserMessage implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue
private Long id;
#Version
private Integer version = 0;
#ManyToOne
#JoinColumn(name = "messageId")
private Message message;
private String user;
private int priority;
private boolean read;
private Date expiry;
private boolean sent;
... getter/setters etc
Message
#Entity(name = "UUMessage")
public class Message implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue
private Long id;
#Version
private Integer version = 0;
private String title;
private String mimeType;
private String message;
private Date received;
private String fromUser;
public Message() {
}
... getter/setters etc
each with their own proxy classes
UserMessageProxy
#ProxyFor(value = UserMessage.class, locator = UserMessageLocator.class)
public interface UserMessageProxy extends EntityProxy {
Long getId();
void setId(Long id);
MessageProxy getMessage();
void setMessage(MessageProxy message);
String getUser();
}
MessageProxy
#ProxyFor(value = Message.class, locator = MessageLocator.class)
public interface MessageProxy extends EntityProxy {
Long getId();
void setId(Long id);
String getTitle();
void setTitle(String title);
}
I have a factory and a context
#Service(value = CentralNotificationService.class, locator = CentralNotificationServiceLocator.class)
public interface CnsRequestContext extends RequestContext {
Request<List<UserMessageProxy>> getMessagesForUser(String user, int start, int length);
}
When I call getMessagesForUser(...) on the client my server side service code gets called, the entries in the database are retrieved and I get a list of UserMessageProxy returned to the client. Unfortunately calling getMessage() on any of these returns null and I can't work out why.
I am not getting any errors or warnings. On the server side I can "see" that the UserMessage does contain the Message objects when the RequestFactory code calls into my service classes.
Why are my objects null? Are there any conditions I am not satisfying?
GWT 2.4 BTW (but also had problems with 2.3)
Your code is probably missing a .with("message"):
When querying the server, RequestFactory does not automatically populate relations in the object graph. To do this, use the with() method on a request and specify the related property name as a String
[…]
It is also necessary to use the with() method to retrieve any properties with types extending ValueProxy. The with() method takes multiple String arguments, so you can specify multiple property names at once. To specify nested properties, use dot notation.
— Source: http://code.google.com/webtoolkit/doc/latest/DevGuideRequestFactory.html#relationships
Related
I use jooq codegen to generate entity classes like this :
public class TCoactivitiesPinan extends BaseEntity implements Serializable {
private static final long serialVersionUID = 2007524284;
private Integer id;
private String openid;
private String tel;
private Timestamp createdtime;
...}
but,I want it to automatically determine that if it's a time type, it automatically adds two fields. like this
public class TCoactivitiesPinan extends BaseEntity implements Serializable {
private static final long serialVersionUID = 2007524284;
private Integer id;
private String openid;
private String tel;
private Timestamp createdtime;
private String createdtime_start; // 创建时间_开始时间
private String createdtime_end; // 创建时间_结束时间
private Integer checkstate;
...
}
Is there any way to solve it? ths.
You can implement your own code generator and extend the POJO's "custom code section" as documented here:
https://www.jooq.org/doc/latest/manual/code-generation/codegen-custom-code
Essentially, just write a class like this:
public class MyGenerator extends JavaGenerator {
#Override
protected void generatePojoClassFooter(TableDefinition table, JavaWriter out) {
for (ColumnDefinition column : table.getColumns()) {
if (column.getType().getType().equals("TIMESTAMP")) {
out.tab(1).println("private String %s_start; // 创建时间_开始时间",
getStrategy().getJavaMemberName(column, Mode.POJO));
out.tab(1).println("private String %s_end; // 创建时间_结束时间",
getStrategy().getJavaMemberName(column, Mode.POJO));
}
}
}
}
And then, configure it as follows:
<configuration>
...
<generator>
<name>com.example.MyGenerator</name>
...
</generator>
</configuration>
Of course, the above solution will only generate the desired members, it will not generate any logic to populate those members when you use the generated POJO type.
i am working on a web application using Spring, Hibernate and SpringMVC,
i am facing a problem with retreiving values from a subclass table using SingleTable inheritance strategy, here are my entities
Client.java (Super class)
#Entity
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(name = "typeClient", discriminatorType = DiscriminatorType.STRING)
public class Client implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int idClient;
private String matricule;
private String statut;
private String secteurDactivite;
private String nomClient;
private String emailClient;
private String numTelephone;
private String adresse;
//constructor
//getter & setters
}
Societe.java (subClass1)
#Entity
#DiscriminatorValue("Societe")
public class Societe extends Client implements Serializable{
private String nomResponsable;
private String emailResponsable;
private String telResponsable;
private String nomSuperieur;
private String emailSuperieur;
private String telSuperieur;
private String commentaire;
//constructeur sans parametre
public Societe() {
}
}
Particulier.java (subclass2)
#Entity
#DiscriminatorValue("Particulier")
public class Particulier extends Client implements Serializable {
private String cin;
//constructeur sans parametres
public Particulier() {
}
}
in my implementation i am using this methode to get a particular client with his ID
ClientDaoImpl.java
public class ClientDaoImpl implements ClientDao {
#PersistenceContext
private EntityManager em;
#Override
public Client getClientByID(int id_client) {
return em.find(Client.class, id_client);
}
When i ran this code i only selected the attributes of the superClass Client.
what i am trying to do is to get a client with its subclass whether it's a Societe or Particulier based on its type or clientID.
Please Help
As you don't know the type of client before querying and only it's ID, you will need to inspect the type and cast after you retrieve the record;
Client client1 = clientDao.getClientById(clientID);
if (client1 instanceof Societe) {
((Societe) client1).getCommentaire();
}
Depending on your use case, it may be useful to map the result of the client query to a ClientDescriptor object which contains all the fields for all client types and returns either nulls or blanks. This means you don't have to keep checking for client type everywhere;
public class ClientDTO {
//client fields
private String nomResponsable = "";
....
//subclass 1 fields.... initialize to empty
//subclass 2 fields .... initialize to empty
public ClientDTO (Client client) {
// set fields for client entity
}
public ClientDTO (Societe societe) {
this (societe);
// set societe fields.
}
// other constructors.
}
You can modify your getClientByID method to accept an additional argument which will say what type of entity your want to retrieve and get back:
public class ClientDaoImpl implements ClientDao {
#PersistenceContext
private EntityManager em;
public <T extends Client> T getByID(int id_client, Class<T> klass) {
return em.find(klass, id_client);
}
}
And you can use this dao in the following manner:
Societe societe = clientDao.getByID(42, Societe.class);
Particulier particulier = clientDao.getByID(43, Particulier.class);
I didn't have this problem before, with other POJOs, I'm not sure what's different this time, but I can't get this working and I could not find an exact solution for this.
I have this POJO called Component (with some Hibernate annotations):
#Entity
#Table(name="component", uniqueConstraints={#UniqueConstraint(
columnNames = {"name", "component_type"})})
public class Component {
#Column(name="id")
#Id #GeneratedValue(strategy=GenerationType.AUTO)
private int id;
#Column(name="name")
private String name;
#Column(name="component_type")
private String componentType;
#Column(name="serial_number")
private int serialNumber;
#Column(name="active_since")
private String activeSince;
#Embedded
private ComponentWearoutModel wearout;
public Component() {
}
public Component(String name, String componentType, int serialNumber, String activeSince,
ComponentWearoutModel wearout) {
this.name = name;
this.componentType = componentType;
this.serialNumber = serialNumber;
this.activeSince = activeSince;
this.wearout = wearout;
}
public ComponentWearoutModel getModel() {
return wearout;
}
public void setModel(ComponentWearoutModel wearout) {
this.wearout = wearout;
}
//more getters and setters
}
ComponentWearoutModel:
#Embeddable
public class ComponentWearoutModel {
private String componentType; //dont mind the stupid duplicate attribute
private Integer componentLifeExpectancy;
private Float componentWearOutLevel;
private Float actionThreshold;
public ComponentWearoutModel() {
}
public ComponentWearoutModel(String componentType, int componentLifeExpectancy, float componentWearOutLevel,
float actionThreshold) {
this.componentType = componentType;
this.componentLifeExpectancy = componentLifeExpectancy;
this.componentWearOutLevel = componentWearOutLevel;
this.actionThreshold = actionThreshold;
}
//getters and setters
}
The sample payload I use:
{
"name": "component name",
"componentType": "airfilter2",
"serialNumber": 573224,
"activeSince": "2016-04-10 17:38:41",
"wearout":
{
"componentType": "airfilter",
"componentLifeExpectancy": 1000,
"componentWearOutLevel": 0.24,
"actionThreshold": 0.2
}
}
And finally the resource class:
#Path("myresource")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON + ";charset=UTF-8")
public class MyResource {
DatabaseManager dm = DatabaseManager.getInstance();
#PUT
#Path("Component")
public Response storeComponent(Component component){
System.out.println("reached");
System.out.println(component.getComponentType()); //okay
System.out.println(component.getModel().getComponentType()); //nullpointerexception
ComponentWearoutModel model = new ComponentWearoutModel("type", 1000, 1f, 0.2f);
component.setModel(model); //this way it's saved in the db just fine
dm.save(component);
return Response.status(Status.OK).entity(component).build();
}
}
Without the prints, only the fields which are not part of the ComponentWearoutModel class are stored in the database table, the other columns are null. So when I try to print one of them, I get an exception, I just dont understand why. If I create a ComponentWearoutModel in the resource method and add it to the component, everything is fine in the database.
UPDATE:
so my mistake was that I named the ComponentWearoutModel attribute as "wearout" in the Component.class, but the autogenerated getters and setter were called getModel/setModel and moxy could not parse my payload because of this. Solution: change the attribute name to "model" in Component class and in payload too.
Please ensure that the attribute names you are using in the POJO are same as what are being sent in the json string.
Since there are no jackson etc annotations being used in your POJO to tell it the corresponding json mapping, the underlying code will directly use the names given in json string. If you are using the string "model", the convertor code will look for a "setModel" method in your POJO.
In the above example, either call everything "model", or "wearable".
I'm very sorry for i explained like fool...
I mean I can't compile because of error.
public class PictureBean implements Serializable
{
public enum CCLtype implements Serializable
{
BY, ND, CO, NN, SA
}
private String picture_rm;
private String picture_url;
private String picture_16_9_url;
private String author;
private String title;
private String description;
private String p_memo;
private String p_original_rate;
private String move_url;
private int like_count;
private int picture_exp_count;
private List<JsonObject> tagList;
private List<JsonObject> categoryList;
private CCLtype ccl;
private String picture_source;
private boolean isUserLiked;
private boolean isUserAdded;
I use this PictureBean.class for contain image datas in my server.
but when I send list of PictureBean data to activity from activity, like below, Eclipse occurred error line.
How could I send list of PictureBean to activity from activity?
'mItems''s dataType is List of PictureBean.
intent.putExtra(CategoryDetailPagerActivity.EXTRA_DATA_CATEGORY_DETAIL_LIST, mItems);
Update:
Don't put the list it self as an extra. send a class object that contain the list as the only member as follow:
public class SerialObject implements Serializable
{
private static final long serialVersionUID = -3975620301776205681L;
public List<PictureBean> myItems;
}
SerialObject sb = new SerialObject();
sb.myItems = mItems;
intent.putExtra(CategoryDetailPagerActivity.EXTRA_DATA_CATEGORY_DETAIL_LIST, sb);
Original Answer:
This is how your class should be:
public class PictureBean implements Serializable
{
private static final long serialVersionUID = 6969933524911660214L;
public enum CCLtype
{
BY, ND, CO, NN, SA
}
private String picture_rm;
private String picture_url;
private String picture_16_9_url;
private String author;
private String title;
private String description;
private String p_memo;
private String p_original_rate;
private String move_url;
private int like_count;
private int picture_exp_count;
private List<JsonObject> tagList;
private List<JsonObject> categoryList;
private CCLtype ccl;
private String picture_source;
private boolean isUserLiked;
private boolean isUserAdded;
}
Same thing for the JsonObject class.
I believe that you don't have to serialise CCLtype
Can you share the error with us? That would be most helpful. Without that information it'd be hard to tell, but my guess is maybe that some of the class types you are trying to make serializable are not types that you can serialize in Android (at least not using the pre-made "Serializable" implementation.
Try commenting out all the types and one at a time uncommenting to find out which type is breaking your serialization. You might be able to write a special serialization method for those types (or switch it to a different type).
Just a guess because you've not yet posted the error, but as the Android docs say "if the local serialVersionUID differs from the serialVersionUID in the serialized data, deserialization will fail with an InvalidClassException." You can work around this, as I had to in my app, by declaring an explicit ID. Put this in your class, to do so, with any Long value you like:
private static final long serialVersionUID = 0L;
I'm using CXF for my webservices.
I have bean
public class Document {
private int id;
private String name;
private String description;
private Date createdDate;
//....getters/setters
}
I have a webmethod interface
#WebMethod(operationName = "SaveDocument")
Document saveDocument(#WebParam(name = "document") Document document);
Is it somehow possible, that input message would be without ID and createdDate? Or should I make two 2 beans. One for input and another for response?
Like
public class DocumentIn {
private String name;
private String description;
//....getters/setters
}
and
public class DocumentOut {
private int id;
private String name;
private String description;
private Date createdDate;
//....getters/setters
}
and webmethod
#WebMethod(operationName = "SaveDocument")
DocumentOut saveDocument(#WebParam(name = "document") DocumentIn document);
You can use the same type as parameter and result. Just primitive types are ever required. If you use
Integer id
instead of int, than it is possible to let it null that means omit the 'id' element in your SOAP XML.
Also if the document is same and you just add 'id' and 'createdDate' on the server side, you can use INOUT parameter as well, see http://tomee.apache.org/examples-trunk/webservice-holder/