Validating a Spring ResourceSupport-ed parent resource as a not empty property in a child resource - rest

I'm looking for guidelines into validating a parent admin resource (AdminResource extending the Spring ResourceSupport class) as not being empty (#NotEmpty) in a child admin module resource (AdminModuleResource extending the Spring ResourceSupport class).
I understand the AdminResource class should also implement the Serializable interface ? Is that the way to go with Spring ResourceSupport-ed resources ?
Here are my resources:
public class AdminResource extends AbstractResource {
private String firstname;
private String lastname;
#NotEmpty
#Email
private String email;
private String password;
private String passwordSalt;
}
public class AdminModuleResource extends AbstractResource {
#NotEmpty
private String module;
#NotEmpty
private AdminResource adminResource;
}
public abstract class AbstractResource extends ResourceSupport {
#JsonProperty("id")
private Long resourceId;
public AbstractResource() {
}
public Long getResourceId() {
return resourceId;
}
public void setResourceId(Long resourceId) {
this.resourceId = resourceId;
}
}
As of now, the #NotEmpty validator annotation gives me the error: No validator could be found for type...
But adding the "implements Serializable" to the resources did not help and the exception remained when using the #NotEmpty validator annotation.
public abstract class AbstractResource extends ResourceSupport implements Serializable {
}
Of course, commenting out the #NotEmpty validator annotation makes the Maven build successful.
Thanks for any directions tips !
Kind Regards,
Stephane

#NotEmpty is only supported for CharSequences (String), Collections, Maps and arrays. It either checks whether the string or collection/array is empty. What does it even mean that a AdminResource is not empty. Do you mean #NotNull?
If it really would make semantically sense to have a #NotEmpty for AdminResource, you would have to implement a custom ConstraintValidator for it and registering it via XML (see also http://beanvalidation.org/1.1/spec/#xml-mapping-constraintdefinition).

Related

Dynamic injection using #SpringBean in wicket

I have a form that based on collected information generates a report. I have multiple sources from which to generate reports, but the form for them is the same. I tried to implement strategy pattern using an interface implementing report generator services, but that led to wicket complaining about serialization issues of various parts of the report generator. I would like to solve this without duplicating the code contained in the form, but I have not been able to find information on dynamic injection with #SpringBean.
Here is a rough mock up of what I have
public class ReportForm extends Panel {
private IReportGenerator reportGenerator;
public ReportForm(String id, IReportGenerator reportGenerator) {
super(id);
this.reportGenerator = reportGenerator;
final Form<Void> form = new Form<Void>("form");
this.add(form);
...
form.add(new AjaxButton("button1") {
private static final long serialVersionUID = 1L;
#Override
protected void onSubmit(AjaxRequestTarget target)
{
byte[] report = reportGenerator.getReport(...);
...
}
});
}
}
If I do it this way, wicket tries to serialize the concrete instance of reportGenerator. If I annotate the reportGenerator property with #SpringBean I receive Concrete bean could not be received from the application context for class: IReportGenerator
Edit: I have reworked implementations of IRerportGenerator to be able to annotate them with #Component and now I when I use #SpringBean annotation I get More than one bean of type [IReportGenerator] found, you have to specify the name of the bean (#SpringBean(name="foo")) or (#Named("foo") if using #javax.inject classes) in order to resolve this conflict. Which is exactly what I don't want to do.
I think the behavior you're trying to achieve can be done with a slight workaround, by introducing a Spring bean that holds all IReportGenerator instances:
#Component
public class ReportGeneratorHolder {
private final List<IReportGenerator> reportGenerators;
#Autowired
public ReportGeneratorHolder(List<IReportGenerator> reportGenerators) {
this.reportGenerators = reportGenerators;
}
public Optional<IReportGenerator> getReportGenerator(Class<? extends IReportGenerator> reportGeneratorClass) {
return reportGenerators.stream()
.filter(reportGeneratorClass::isAssignableFrom)
.findAny();
}
}
You can then inject this class into your Wicket page, and pass the desired class as a constructor-parameter. Depending on your Spring configuration you might need to introduce an interface for this as well.
public class ReportForm extends Panel {
#SpringBean
private ReportGeneratorHolder reportGeneratorHolder;
public ReportForm(String id, Class<? extends IReportGenerator> reportGeneratorClass) {
super(id);
IReportGenerator reportGenerator = reportGeneratorHolder
.getReportGenerator(reportGeneratorClass)
.orElseThrow(IllegalStateException::new);
// Form logic omitted for brevity
}
}
As far as I am able to find, looking through documentation and even the source for wicket #SpringBean annotation, this isn't possible. The closest I got is with explicitly creating a proxy for a Spring bean based on class passed. As described in 13.2.4 Using proxies from the wicket-spring project chapter in Wicket in Action.
public class ReportForm extends Panel {
private IReportGenerator reportGenerator;
private Class<? extends IReportGenerator> classType;
private static ISpringContextLocator CTX_LOCATOR = new ISpringContextLocator() {
public ApplicationContext getSpringContext() {
return ((MyApplication)MyApplication.get()).getApplicationContext();
}
};
public ReportForm(String id, Class<? extends IReportGenerator> classType) {
super(id);
this.classType = classType;
final Form<Void> form = new Form<Void>("form");
this.add(form);
...
form.add(new AjaxButton("button1") {
private static final long serialVersionUID = 1L;
#Override
protected void onSubmit(AjaxRequestTarget target)
{
byte[] report = getReportGenerator().getReport(...);
...
}
});
}
private <T> T createProxy(Class<T> classType) {
return (T) LazyInitProxyFactory.createProxy(classType, new
SpringBeanLocator(classType, CTX_LOCATOR));
}
private IReportGenerator getReportGenerator() {
if (reportGenerator = null) {
reportGenerator = createProxy(classType);
}
return reportGenerator;
}
}

Json custom deserializer not called in Websphere

I have simple class and field id is annotated with custom deserializer.
public class TestRequest implements Serializable {
#NotNull
#Pattern(regexp = "^[a-zA-Z0-9=+]*$")
#JsonDeserialize(using = StringDeserializer.class)
#JsonProperty
private String id;
//getter
//setter
}
and the custom deserializer class :
public class StringDeserializer extends JsonDeserializer<String> {
#Override
public String deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) {
Iterator<String> iterator = jsonParser.readValuesAs(String.class);
String id = iterator.next();
return id + "0000";
}
}
When i test with with Jersey REST test, the deserilizer is called and works as expected. But with websphere it does not called. Any idea why its not called.
I am using jaxrs 1.1
You may need to add the #Provider annotation to your StringDeserializer class, otherwise the JAX-RS runtime will not recognize the class as a provdier.
Even though your class extends JsonDeserializer<String>, which itself is probably annotated with #Provider, the JAX-RS runtime will not scan libraries for annotations, as doing negatively impacts performance.
I made it working in Websphere by moving the annotation #JsonDeserialize(using = StringDeserializer.class) to setter method of the class
public class TestRequest implements Serializable {
#NotNull
#Pattern(regexp = "^[a-zA-Z0-9=+]*$")
#JsonProperty
private String id;
#JsonDeserialize(using = StringDeserializer.class)
public setId(String id){
this.id=id;
}
//getter
//setter
}

TomEE Resteasy JAX-B -> Can not get Nested Object

I'm working on a RestWebService using Resteasy. The basic implementation works fine. Know I tried to return a Complexer- Object through rest...
Actually its pretty easy..I thought. I'm getting a problem because of my nested object (Address)...
What I try is this:
#XmlRootElement(name = "person")
#XmlAccessorType(XmlAccessType.FIELD)
public class Person implements Serializable {
private static final long serialVersionUID = 1199647317278849602L;
private String uri;
private String vName;
private String nName;
private Address address;
.....
#XmlElementWrapper(name="Former-User-Ids")
#XmlElement(name="Adress")
public Address getAddress() {
return address;
}
....
Address looks like this:
#XmlRootElement(name = "address")
#XmlAccessorType(XmlAccessType.FIELD)
public class Address {
private String uri;
private String street;
private String city;
public String getCity() {
return city;
}
public String getStreet() {
return street;
}
....
The Restservice looks like this. It worked perfect without the address object..
#Path("/getPersonXML/{personNumber}")
#GET
#Produces(MediaType.APPLICATION_XML)
public Patient getPatientXML(#PathParam("personNumber") String personNumber) throws ParseException {
Address a1 = new Address("de.person/address/" + "432432","Teststret12","TestCity", "32433", "TestCountry", "081511833");
Patient p1 = new Person();
p1.setAddress(a1);
p1.setUri("de.spironto/person/"+ "432432");
p1.setnName("Power");
p1.setvName("Max");
return p1;
}
At the moment I'm always getting a
javax.xml.bind.JAXBException:
Any Ideas?
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.
PROBLEM
The #XmlElementWrapper annotation must be used with a collection property. This means you can have:
#XmlElementWrapper
public List<PhoneNumber> getPhoneNumbers() {
return phoneNumbers;
}
But not
#XmlElementWrapper
public Address getAddress() {
return address;
}
SOLUTION #1 - Using Any JAXB Proivder
You could use an XmlAdapter to accomplish this (see linked answer below):
Access attribute of internal element in the most simple way
SOLUTION #2 - Using EclipseLink JAXB (MOXy)
You could leverage the #XmlPath extension to map this use case:
#XmlPath("Former-User-Ids/Address")
public Address getAddress() {
return address;
}
For More Information
http://blog.bdoughan.com/2010/07/xpath-based-mapping.html
http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html
After building a small marshaller test. I got the failure that there are several properties with the same name. So I tried to delete all #XML_Eleemets annotations in the Address class.
That worked for me...

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 {
...
}