Command Objects in Spring - java

I have a command object composed of primitive fields and an object field. How do I bind my form fields to the fields in the object?
I tried doing this but to no avail
<form:form commandName="course" method="POST">
<form:input path="activity.activity"/>
.
.
.
</form:form>
I get this error
org.springframework.beans.NotReadablePropertyException:
Invalid property 'course' of bean class
My Command class is like this
public class Course {
private long id;
private String owner;
private String title;
private List<LearningActivity> activity = new ArrayList<LearningActivity>();
//getters and setters
}
public class LearningActivity {
private long ID;
private String activity;
private String link;
//getters and setters
}

Your list either needs to be pre-populated with as many LearningActivity objects as you plan to refer to (using activity[0], activity[1], etc.) or it needs to be a lazy list. A lazy list is a list that will populate itself with empty objects when a given index is referenced.
A comment indicates that you're trying to use Apache Commons LazyList, which ought to work -- are you missing an import directive? However, as an alternative there is a Spring lazy list implementation called AutoPopulatingList.

Two possible issues here:
activity.activity is invalid (unless your getters do not correspond to your member variables) because Course.activity is a list. You need to address a particular list element - e.g. activity[0].activity. You'll also have to make sure it actually exists.
Have you configured your FormController correctly? Does it pass Course instance to view as it should? Take a look at Spring MVC tutorial for an example.
If after you've fixed #1 and verified that #2 is done correctly the error doesn't go away, please post more details (FormController mapping / source).

Related

Deserialization of File type from Angular to Java using Jackson

In my REST application developed using SpringBoot and Angular, I need to send a REST request to SpringBoot back end in order to save a object into the database.
In the front end, user fills up a form and submits. Following is the interface from which a object is created in order to be sent to the backend as a REST call.
export interface TenderToPost{
id: number;
name: string;
description: string;
images: File[];
referenceNumber: string;
}
The backend should deserialize the above object to a object of Following class in Java.
public class TenderDTO implements Serializable{
private long id;
private String name;
private String description;
private List<MultipartFile> images;
private String referenceNumber;
// default constructor
// geters and setters
}
As shown above, I need to accept the File sent from frontend as a MultipartFile.
However, when the request is sent from the front end, Jackson gives me the error
Can not construct instance of
org.springframework.web.multipart.MultipartFile: abstract types either
need to be mapped to concrete types, have custom deserializer, or
contain additional type information
I am aware that that this error comes since I have used MultipartFile interface as the type of my images list.
What I thought of as the solution for this, is letting Jackson know to what type the list should be deserialized into using an annotation. So, I used following
#JsonDeserialize(contentAs = CommonsMultipartFile.class)
private List<MultipartFile> images;
CommonsMultipartFile is an implementation of MultipartFile. That is why I used it.
Now I get the following error.
Can not construct instance of
org.springframework.web.multipart.commons.CommonsMultipartFile: no
suitable constructor found, can not deserialize from Object value
(missing default constructor or creator, or perhaps need to add/enable
type information?)
Do I need to change the setter for the images list? Or is my whole approach incorrect?
Kindly show me the way how I should correct this.
Try to use #JsonPropertyDescription to construct object.
#JsonPropertyDescription example

mongoDb morphia POJO property with read only access

I have created a POJO class in morphia to save data object to MongoDB ,
I have a property called 'unitPrice', i want to keep this as read only property, mean not allow to modify DB value once it save to mongo,
Is there a morphia annotation to do this or else,
Is it possible to bind #NotSaved annotation to the property at run time ?
This is my POJO
#Entity("items")
public class Items {
private int id;
private int sequence;
private int unitPrice;
}
Thanks
BR
Ero
I don't know of a way to bind #NotSaved at runtime, but I could think of a (hacky) workaround:
Set the attribute in the constructor (Morphia will still require the no-args constructor)
Don't provide a setter, just a getter for the attribute
It ain't pretty, but it should get the job done.

How to define forms to persist complex objects in Spring?

I need to define a from to create instances of one of my objects. This is an easy task and I already have some, but this specific object has a reference to other object that I must define in the form. How can this be done? I know I could ask the user to enter de id, store it in a DTO and get the real object later but I suppose that this is not the best way to accomplish this. What can I do?
I put here my entities:
#Entity
public class Route {
#Id
#GeneratedValue
private Long id;
#Column(nullable = false)
private Long distance;
#Column(nullable = false)
private String name;
private String description;
#ManyToOne
#JoinColumn
private Place origin;
}
And this is the references object:
#Entity
public class Place {
#Id
#GeneratedValue
private Long id;
#Column(nullable = false)
private String name;
private Long latitude;
private Long longitude;
private String imagePath;
#OneToMany(mappedBy = "origin", cascade = CascadeType.REMOVE)
private Set<Route> originRoutes;
}
It actually depends on what is the use case in more details. Let's think of couple of possibilities:
Create a Place together with some Routes instantly at one go - in this case I would implement the view so that it creates a complex structure reflecting the entities one to one like you have them defined for JPA, and passes in single POST request. We basically assume that there is limited number of routes that are always created together with places. Routes cannot be shared among different Places as it makes no sense.
#RequestMapping(method = POST, value = "/places")
public CreatePlaceResponse createPlace(#RequestBody Place place) {
...
}
Create a Place and provide Routes in subsequent requests. - if we want more flexibility and/or expect the number of routes assigned to each place to be large, we may first create a Place and after that use another request to assign Routes to it (by referring to a place id). This way you let the user create the whole structure step by step, plus you give a possibility to add a Route later on.
#RequestMapping(method = POST, value = "/places")
public CreatePlaceResponse createPlace(#RequestBody Place place) {
...
}
#RequestMapping(method = POST, value = "/places/{placeId}")
public AddRouteResponse addRoute(#RequestBody Route route) {
...
}
Depending on case you can also think of bulk creation of Routes as well, so passing a list of Routes to an already created place.
On the UI side I can see this working using either a hidden field to store the place id in response to the text entered or a 'fancy' select such as one of these at the below which let you type into the select to filter and won't load 1000s of record in memory at once:
http://silviomoreto.github.io/bootstrap-select/
Either way, you are going to bind the hidden field or the selected option to:
route.place
e.g.
<form:hidden path="place" value="id_of_place_updated_by_javascript" />
or
<form:select path="place">
You will then register a converter which will convert the submitted value to the required type i.e. Place. On submit your converter takes the Place ID and retrieves the corresponding Place from the Database. The framework will then bind the Place returned by the Converter to the Route backing the form.
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/validation.html#core-convert
See here for an example using a Formatter to do the conversion:
http://springinpractice.com/2012/01/07/making-formselect-work-nicely-using-spring-3-formatters
In the final example you would just go off to the database to get the relevant entity rather than creating a new instance.

Morphia - change class associated with a collection

I'm trying to phase out an older java codebase that uses MongoDB/Morphia. During this transition, I'd like the new platform to write to the same MongoDB database/collections so that each can live side by side for a little while. That part I'm doing alright with. My issue is that in the new platform, I need a different package/class structure for the objects I'm mapping with morphia than what is currently in the collection.
For instance, in the old platform I've got this class:
package com.foo;
#Entity
public class Bar {
#Id private String id;
private String name;
...
}
In my mongo database, I now have a collection "Bar" and its documents have the className attribute set to "com.foo.Bar". That's all wonderful.
What I'd like to do in the new platform is create a brand new class in a different package to represent that entity, but have it interact with mongo in the same way. I'm hoping to be able to do something like this:
package com.foo.legacy;
#Entity("com.foo.Bar")
public class LegacyBar {
#Id private String id;
private String name;
...
}
I realize the above doesn't work, but if I change the annotation to #Entity("Bar") I don't get any errors, but when I look up entities by id, I always get null back.
So... is there any way for me to have 2 separate VMs with 2 class structures and 2 different configurations of Morpha such that each can write to the same database/collection in the same fashion?
If I change LegacyBar to just "Bar" and create it in a package called "com.foo" then everything works as expected. I would just REALLY prefer to have the flexibility to quarantine all of this legacy data in a semi-clean fashion.
Do you even need the className attribute?
You can disable it with
#Entity(value = "Bar", noClassnameStored = true)
and drop the attribute in the database.
Quoting the official documentation:
Why would you need it?
This is mainly used when storing different
entities in the same collection and reading them back as the base or
super class.
If you don't do this, it should be an easy workaround to allow different package structures.

GWT + GAE datastore Key and Text Java Error

I would like to create an application that saves and retrieves records to the GAE server. I followed the tutorial "Deploying to Google App Engine" http://code.google.com/webtoolkit/doc/latest/tutorial/appengine.html to get started.
I have the StockWatcher application working now, but in my application I need to store a String that can be large (>10KB). I read that I can't use a Java String type to store large strings and need to use the Text data type instead.
I think by Text, they mean: com.google.appengine.api.datastore.Text, but it would be nice to confirm this is correct. ???
Regardless, I can't get Text to work. After some research it appears both the types Key and Text can only be used in the server code and not the client code. It seems that this is because the source code is not available for these classes and GWT needs the source to create the JavaScript code on the client's computer. At least that my current working hypothesis as to why I'm getting the following errors:
21:52:52.823 [ERROR] [myapp] Line 15: The import com.google.appengine.api.datastore cannot be resolved
21:52:52.951 [ERROR] [myapp] Line 103: Key cannot be resolved to a type
21:52:53.011 [ERROR] [myapp] Line 106: Text cannot be resolved to a type
I use the following fields in a class in a shared folder.
shared/MyDataRecord
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Key id;
#Persistent
private Text description;
MyDataRecord class in a shared folder because I wanted to use to send back all the fields in one get method return rather than multiple individual field get methods. Here's how I use MyDataRecord class in my server/DataServiceImpl.java class
public class DataServiceImpl extends RemoteServiceServlet implements DataService
{
...
#Override
public MyDataRecord getDataRecord() throws NotLoggedInException
{
...
I've seen some posted solutions suggest using non-standard, 3rd party libraries, like http://www.resmarksystems.com/code/. I couldn't get this one installed, but even if I could, I'd prefer a different solution. Storing Text must be such a common task that I'd prefer to solve this using what is considered a standard solution.
I could change my code to return each field in multiple get methods instead of an single return of a MyDataRecord instance. However, even if that works, that would be significantly more work and more difficult to maintain over time. However, if this is what is normally expected, then that's what I'll do.
I'd like to solve this using what is considered best practices by GWT and GAE. A simple example or tutorial would go a long way, but I can't find one.
Are there example programs/tutorials that show what GWT considers best practices for storing and retrieving large strings?
I am a newbie with both GWT and GAE (as well as web development), please consider this in any responses, thanks.
No Snark Please
The serializable POJO. Note the NotPersistent annotation for description
package com.my.project.shared;
#PersistenceCapable(identityType=IdentityType.APPLICATION,detachable="true")
public class MyParent implements Serializable {
#PrimaryKey
#Persistent(valueStrategy=IdGeneratorStrategy.IDENTITY)
private Long id;
#NotPersistent //Note the NotPersistent annotation. GAE won't persist this value in big table
private String description;
}
The second POJO. Notice the package
package com.my.project.server;
#PersistenceCapable(identityType=IdentityType.APPLICATION,detachable="true")
public class MyChild implements Serializable{//Not really required to implement Serializable
#PrimaryKey
#Persistent(valueStrategy=IdGeneratorStrategy.IDENTITY)
private Long id;
#Persistent
private Long parentID;//Reference to the MyParent
#Persistent
private Text description;//The actual value of the description variable.
}
Notice the parent ID mapped in the child. While retrieving you will need to identify which child belongs to which parent.
In pseudo code
1) Load parent from DB
2) Identify child for this parent, and load it
3) Convert child.description->parent.description
4) Now you have a fully constructed parent POJO which is serializable. Send it to the UI
Just reverse the procedure on the way back from UI to GAE.
1) Define a NotPersistent field in your serializable POJO private String description
2) Define a new POJO on the server side which will have private Text description
3) When you persist/load the original POJO, retrieve the new POJO and populate the String description from the Text description

Categories

Resources