How to read the new XStreamConverter parameters? - xml-serialization

Since version 1.4.2 of XStream, the XStreamConverter annotation takes additional parameters (very good feature and just what I need).
#XStreamConverter(value=CustomXStreamConverter.class, strings={xyz"})
private List<String> phones;
But how can I read this values (xyz) in my custom converter?
public class CustomXStreamConverter implements Converter {
//?
}

I figure out the solution, just override the class constructor in order to receive the parameter.
public class CustomXStreamConverter implements Converter {
private String alias;
public ListToStringXStreamConverter(String alias) {
super();
this.alias = alias; //xyz
}
//...

Related

Any way to reference an attribute of a parameter in the query?

Is there any way to reference an attribute of a parameter that is part of a query for a JPA repository?
My sample is
#Entity
public class Matchday implements Serializable {
#Id
private int matchdayNumber;
//..
//setters and getters defined
//..
//hashCode and equals methods overridden
}
public interface MyRepository extends JpaRepository<Matchday, Integer> {
#Query("... WHERE t.matchday.matchdayNumber < :matchday.matchdayNumber - 1;")
public findByCriteria(Matchday matchday);
}
The construction :matchday.matchdayNumber does not seem to be a valid syntax. Is there any other way to do it than passing the int value for matchdayNumber instead of a reference to Matchday object to this method?
Looks like this is possible with Spring JPA Data which allows SpEL in queries.
public interface MyRepository extends JpaRepository<Matchday, Integer> {
#Query("... WHERE t.matchday.matchdayNumber < :#{#matchday.matchdayNumber - 1}")
public findByCriteria(Matchday matchday);
}

Morphia converter calling other converters

I want to convert Optional<BigDecimal> in morphia. I created BigDecimalConverter, and it works fine. Now I want to create OptionalConverter.
Optional can hold any object type. In my OptionalConverter.encode method I can extract underlying object, and I'd like to pass it to default mongo conversion. So that if there is string, I'll just get string, if there is one of my entities, I'll get encoded entity. How can I do it?
There are two questions:
1. How to call other converters?
2. How to create a converter for a generic class whose type parameters are not statically known?
The first one is possible by creating the MappingMongoConveter and the custom converter together:
#Configuration
public class CustomConfig extends AbstractMongoConfiguration {
#Override
protected String getDatabaseName() {
// ...
}
#Override
#Bean
public Mongo mongo() throws Exception {
// ...
}
#Override
#Bean
public MappingMongoConverter mappingMongoConverter() throws Exception {
MappingMongoConverter mmc = new MappingMongoConverter(
mongoDbFactory(), mongoMappingContext());
mmc.setCustomConversions(new CustomConversions(CustomConverters
.create(mmc)));
return mmc;
}
}
public class FooConverter implements Converter<Foo, DBObject> {
private MappingMongoConverter mmc;
public FooConverter(MappingMongoConverter mmc) {
this.mmc = mmc;
}
public DBObject convert(Foo foo) {
// ...
}
}
public class CustomConverters {
public static List<?> create(MappingMongoConverter mmc) {
List<?> list = new ArrayList<>();
list.add(new FooConverter(mmc));
return list;
}
}
The second one is much more difficult due to type erasure. I've tried to create a converter for Scala's Map but haven't found a way. Unable to get the exact type information for the source Map when writing, or for the target Map when reading.
For very simple cases, e.g. if you don't need to handle all possible parameter types, and there is no ambiguity while reading, it may be possible though.

gwt rpc serialize generic class

I need to pass a class object through the gwt rpc connection as a generic but it seems that rpc does not cooperate with it. The class is serialized using the java.io.Serializable. I have checked it using the gwt IsSerializable but i still have the error.
Here is my code
MySource.java
#SuppressWarnings("serial")
#PersistenceCapable
#Inheritance(strategy = InheritanceStrategy.SUBCLASS_TABLE)
public abstract class MySource implements Serializable {
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Long id;
#Persistent
private String userId;
#Persistent
private String title;
#Persistent
private String description;
#Persistent
private String blobKey;
#Persistent
private String youtubeLink;
#Persistent
private String personalLink;
#Persistent
private Date submitedDate;
#Persistent
private float price;
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getBlobKey() {
return blobKey;
}
public void setBlobKey(String blobKey) {
this.blobKey = blobKey;
}
public String getYoutubeLink() {
return youtubeLink;
}
public void setYoutubeLink(String youtubeLink) {
this.youtubeLink = youtubeLink;
}
public String getPersonalLink() {
return personalLink;
}
public void setPersonalLink(String personalLink) {
this.personalLink = personalLink;
}
public Date getSubmitedDate() {
return submitedDate;
}
public void setSubmitedDate(Date submitedDate) {
this.submitedDate = submitedDate;
}
public Long getId() {
return id;
}
}
AndroidSource.java
#SuppressWarnings("serial")
#PersistenceCapable
public class AndroidSource extends MySource{
public AndroidSource() {
super();
}
}
CategoryBrowseService.java which is the remoteservice model
#RemoteServiceRelativePath("categoryService")
public interface CategoryBrowseService extends RemoteService{
ArrayList<MySource> getSourceList(Class<? extends MySource> classType);
}
CategoryBrowseServiceAsync.java
public interface CategoryBrowseServiceAsync {
void getSourceList(Class<? extends MySource> classType,
AsyncCallback<ArrayList<MySource>> callback);
}
CategoryBrowsePresenter.java where the rpc is called
private void retrieveSources(Class<? extends MySource> classType) {
CategoryBrowseServiceAsync rpcService = GWT.create(CategoryBrowseService.class);
rpcService.getSourceList(classType, new AsyncCallback<ArrayList<MySource>>() {
#Override
public void onFailure(Throwable caught) {
Window.alert("Ooops!!!Sorry!Something went wrong.I am still beta!");
}
#Override
public void onSuccess(ArrayList<MySource> result) {
sourceList = result;
display.setSourceContent(sourceList);
}
});
}
CategoryBrowseServiceImpl.java
#SuppressWarnings("serial")
public class CategoryBrowseServiceImpl extends RemoteServiceServlet implements CategoryBrowseService{
private SourceDatastore dataStore;
public CategoryBrowseServiceImpl() {
dataStore = new SourceDatastore();
}
#Override
public ArrayList<MySource> getSourceList(Class<? extends MySource> classType) {
return dataStore.getSources(classType);
}
}
Here is the error that i get.
Compiling module com.sourcebay.SourceBay
Scanning for additional dependencies: file:/home/santaris/workspace/SourceBay/src/com/sourcebay/client/presenter/mybay/browse/CategoryBrowsePresenter.java
Computing all possible rebind results for 'com.sourcebay.client.model.mybay.browse.CategoryBrowseService'
Rebinding com.sourcebay.client.model.mybay.browse.CategoryBrowseService
Invoking generator com.google.gwt.user.rebind.rpc.ServiceInterfaceProxyGenerator
Generating client proxy for remote service interface 'com.sourcebay.client.model.mybay.browse.CategoryBrowseService'
[ERROR] java.lang.Class<T> is not assignable to 'com.google.gwt.user.client.rpc.IsSerializable' or 'java.io.Serializable' nor does it have a custom field serializer (reached via java.lang.Class<? extends com.sourcebay.shared.source.MySource>)
[ERROR] java.lang.Class<T> has no available instantiable subtypes. (reached via java.lang.Class<? extends com.sourcebay.shared.source.MySource>)
[ERROR] subtype java.lang.Class<T> is not assignable to 'com.google.gwt.user.client.rpc.IsSerializable' or 'java.io.Serializable' nor does it have a custom field serializer (reached via java.lang.Class<? extends com.sourcebay.shared.source.MySource>)
[ERROR] Errors in 'file:/home/santaris/workspace/SourceBay/src/com/sourcebay/client/presenter/mybay/browse/CategoryBrowsePresenter.java'
[ERROR] Line 75: Failed to resolve 'com.sourcebay.client.model.mybay.browse.CategoryBrowseService' via deferred binding
The paradox is that when i am running my application through the eclipse plugin everything works fine. Could anyone help me please? I have checked to fix the problem through the DTO solution without any success. Moreover i have tried to implement a CustomFieldSerializer as Google suggests without any success too.
Thanks in advance,
Stefanos Antaris
P.S. Sorry for the huge post :-)
Well the problem is that you trying to transport a Class object over the network. I have no idea why it is working in dev mode (I've tried it on local project and it failed), but it shouldn't work. You have to use something else instead of Class name for example String, which will contain a name of class. Theoretically it can work if you create CustomFieldSerializer for Class, but using String instead of Class will be easier.
Classes with persistence annotations can work well on the server side, but if you want to pass its data to the client you must create a plain java serializable class to transport data from server to client.
As noted in the previous answer, persistence annotations are not supported in the client side, as they cannot be translated to equivalent javascript code (and it makes sense since the client doesn't have the responsability of persistence).
It could be that the persistence-related annotations in MySource.java make it implossible to translate to javascript. Try removing the annotations to see if it's related. Also make sure that MySource.java is in a package declared as translatable in the module xml file ("source" element).
Try using implements Serializable for defining you class.
I mean like this:
public class AndroidSource extends MySource implements Serializable{
public AndroidSource() {
super();
}
}
Your RPC Services must deal just with Serializable Objects. Domain classes are not translatable to JavaScript So GWT can't send and receive via network (RPC Protocole) such objects. You need to create DTO classes (wich shadows domain class) implementing java.io.Serializable and then reconfigure all your RPC Service to use in input DTOs and output DTOs. Good Luck for your project.

How to edit a Set<? extends EntityProxy> with GWT Editor framework?

for sake of simplicity:
public class Person
{
String name;
Set<Address> addresses;
}
public class Address
{
String city;
String street;
}
with and matching
public interface PersonProxy extends EntityProxy
{
public String getName();
public Set<AdressProxy> getAddresses();
}
and
public interface AdressProxy extends EntityProxy
{
public String getCity();
public String getStreet();
}
I got UiBuinder classes to edit AddressProxy
and it clear to me how to use ListEditor in case if I got List but data is Set in the Person class
how do I use Editor Framework to edit them?
Or may be how do I convert Set to List when it becomes PersonProxy?
I did an attempt to put a kind of adapter Editor class that would implement
LeafValueEditor<Set<AddressProxy>>
and then inside of the LeafValueEditor.setValue() move to a List and start a new driver.edit() on a separate Editor hierarchy that takes care of List editing but with now luck.
You should create a CompositeEditor<Set<AddressProxy>, AddressProxy, AddressEditor>, similar to a ListEditor but handling a Set instead of a List.
I suppose you could somehow delegate to a ListEditor though I'm really not sure.
I've done it with Points and Routes (one Route contains N Points):
Route (Composite):
#UiField
TextBox name;
#Ignore
#UiField
FlexTable listPoints;
PointsEditor pointsEditor = new PointsEditor();
....
pointsEditor.add(String id);
PointsEditor:
public class PointsEditor implements HasRequestContext<List<PointProxy>>, ValueAwareEditor<List<PointProxy>> {
List<PointProxy> points = new ArrayList<PointProxy>();
public void add(String id) {
PointProxy point = ctx.create(PointProxy.class);
point.setId(id);
points.add(point);
}
Route (server side):
#Embedded
private List<Point> points = new ArrayList<Point>();
RouteProxy
public interface RouteProxy extends EntityProxy {
abstract List<PointProxy> getPoints();
abstract void setPoints(List<PointProxy> points);
PointProxy
public interface PointProxy extends ValueProxy {
...
}

How to get access to underlying POJO from GWT Editor class

I have a HashMap inside my POJO that I am using the Editor framework in GWT to edit. While I have access to the standard member variables bound through thier getters/setters, I don't know how to access the values inside the HashMap. How do I get access to the underlying POJO that is being edited through my editor that is using the SimpleBeanEditorDriver?
My POJO:
#Entity(noClassnameStored=true)
public class ProfileConfig extends BaseEntity {
#Indexed(unique=true)
private String name;
private boolean isDefault;
private HashMap<ProfileID, ProfileInfo> profiles= new HashMap<ProfileID, ProfileInfo>();
public ProfileInfo getProfile(ProfileID id) {
return profiles.get(id);
}
public void setProfile(ProfileID id, ProfileInfo p) {
profiles.put(id, p);
}
My Editor:
public class ProfileConfigEditor extends Composite implements ManagedObjectEditor<ProfileConfig> {
private static ProfileConfigEditorUiBinder uiBinder = GWT.create(ProfileConfigEditorUiBinder.class);
interface ProfileConfigEditorUiBinder extends UiBinder<Widget, ProfileConfigEditor> {
}
private UserManager userManager;
#UiField
CellList Profiles;
#UiField
TextBox name;
#UiField
CheckBox isDefault;
So given that I have a list of valid Profile ids from the userManager, how do I go about calling the getProfile method from my POJO from within my Editor?
What you need is a ValueAwareEditor.
public class ProfileConfigEditor extends Composite implements ManagedObjectEditor<ProfileConfig>, ValueAwareEditor<ProfileConfig> {
void setValue(ProfileConfig value){
// TODO: Call ProfileConfig.getProfile()
}
void flush(){
// TODO: Call ProfileConfig.setProfile()
}
// ... Other methods here
Alternatively, if you want more of a challenge, you can look at rolling your own CompositeEditor, for example see the source code for ListEditor. In your case, you would implement a CompositeEditor<ProfileConfig, ProfileInfo, MyNewProfileInfoEditor>. You can this of this as "This editor will take a ProfileConfig object, extract one or more ProfileInfo objects and edit it with one or more MyNewProfileInfoEditor editors"