play framekwork 2.2. - ebean model save time from request - angularjs

i have these model
#Entity
#Table(name = "recipe")
public class Recipe extends Model {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
public Long id;
#NotNull
#Constraints.Required
public String title;
#Column(name = "short_description")
public String shortDescription;
#Column(columnDefinition = "TEXT")
public String ingredients;
#Column(columnDefinition = "TEXT")
public String cooking;
#NotNull
#Constraints.Required
#Formats.DateTime(pattern="HH:mm:ss")
public Time time;
now i'd like to save data comming from angular js with restangular. all parameters were provieded in the controller but i get a error:
{"time":["Invalid value"]}
all data were strings in the request. i guess thats the problem. but i don't want cast it by my self, because then i loose the play form validation...
do you can give me any hints?
thanks a lot!

Java and dates/times do not play nice together unfortunately. I would remove the #Formats annotation and just pass in the 'unix time' because that is what the Time class expects. You can do this pretty easily on the angular side by implementing the momentjs library. if you are getting the dates in the format HH:mm:ss then in your angular controller use the following code to format the time to unix time:
var time = moment(str, "HH:mm:ss").format("X");
where str is a string represtation of the time you are formatting. then pass time in as the parameter.
if i completely misunderstood the question and you are retrieving the time from the database and not saving the time to the database then just flip the above method.
var time = moment(str, "X").format("HH:mm:ss");
where str is the time you retrieved from the database.

Related

Spring + Hibernate + MS SQL server - UTC time zone

I have developed simple application with Spring 4.2.5 + Hibernate 5.1.0 - database system is MS SQL Server 2014.
From few days I am struggling with correct storing time + timezone in database.
Requirements that I need to fulfill is:
Save all dates in UTC time zone.
Store timezone in database column value.
To achieve it I created model called MyComment:
#Entity
#Table(name = "MY_COMMENT")
#EntityListeners(value = { MyCommentListener.class })
#Audited
public class MyComment implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "ID")
private Long id;
#Column(name = "DATE_", nullable = false)
private Timestamp date;
...
}
To enforce saving dates in UTC time zone I used Jadira framework:
hibProperties.put("jadira.usertype.autoRegisterUserTypes", true);
hibProperties.put("jadira.usertype.javaZone", "UTC");
hibProperties.put("jadira.usertype.databaseZone", "UTC");
However during each create/update operation of MyComment object, MyCommentListener is getting date from my local timezone (not UTC date!):
public class MyCommentListener {
#PreUpdate
#PrePersist
public void setLastUpdate(MyComment myComment) {
myComment.setDate(new Timestamp(System.currentTimeMillis()));
}
}
Do you know how can I solve this issue?
Should I use other date type in my model? Different than Timestamp?
What kind of type should be DATE_ column in MS SQL server database?
I will appreciate any help. Thank you.
AFAIK, the problem is with listener. Replace the following code in listener and verify. Change the date format as per your need.
#PreUpdate
#PrePersist
public void setLastUpdate(MyComment myComment) {
SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
myComment.setDate(dateFormat.getCalendar().getTime());
}
You can set a timezone property in the application properties file as below.
spring.jpa.properties.hibernate.jdbc.time_zone=UTC
It was very strange for me that there's no property in Spring to set up default TimeZone - at least I do not know about it.
After some googling I found out that the best place in Spring to set time zone is WebApplicationInitializer, so I prepared following code:
public class MyWebApplicationInitializer implements WebApplicationInitializer {
#Override
public void onStartup(final ServletContext servletContext) throws ServletException {
setupTimeZone();
}
private void setupTimeZone() {
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
}
}

How to use dynamic schema in spring data with mongodb?

Mongodb is a no-schema document database, but in spring data, it's necessary to define entity class and repository class, like following:
Entity class:
#Document(collection = "users")
public class User implements UserDetails {
#Id private String userId;
#NotNull #Indexed(unique = true) private String username;
#NotNull private String password;
#NotNull private String name;
#NotNull private String email;
}
Repository class:
public interface UserRepository extends MongoRepository<User, String> {
User findByUsername(String username);
}
Is there anyway to use map not class in spring data mongodb so that the server can accept any dynamic JSON data then store it in BSON without any pre-class define?
First, a few insightful links about schemaless data:
what does “schemaless” even mean anyway?
“schemaless” doesn't mean “schemafree”
Second... one may wonder if Spring, or Java, is the right solution for your problem - why not a more dynamic tool, such a Ruby, Python or the Mongoshell?
That being said, let's focus on the technical issue.
If your goal is only to store random data, you could basically just define your own controller and use the MongoDB Java Driver directly.
If you really insist on having no predefined schema for your domain object class, use this:
#Document(collection = "users")
public class User implements UserDetails {
#Id
private String id;
private Map<String, Object> schemalessData;
// getters/setters omitted
}
Basically it gives you a container in which you can put whatever you want, but watch out for serialization/deserialization issues (this may become tricky if you had ObjectIds and DBRefs in your nested document). Also, updating data may become nasty if your data hierarchy becomes too complex.
Still, at some point, you'll realize your data indeed has a schema that can be pinpointed and put into well-defined POJOs.
Update
A late update since people still happen to read this post in 2020: the Jackson annotations JsonAnyGetter and JsonAnySetter let you hide the root of the schemaless-data container so your unknown fields can be sent as top-level fields in your payload. They will still be stored nested in your MongoDB document, but will appear as top-level fields when the ressource is requested through Spring.
#Document(collection = "users")
public class User implements UserDetails {
#Id
private String id;
// add all other expected fields (getters/setters omitted)
private String foo;
private String bar;
// a container for all unexpected fields
private Map<String, Object> schemalessData;
#JsonAnySetter
public void add(String key, Object value) {
if (null == schemalessData) {
schemalessData = new HashMap<>();
}
schemalessData.put(key, value);
}
#JsonAnyGetter
public Map<String, Object> get() {
return schemalessData;
}
// getters/setters omitted
}

Is there any way to save only one property of an Entity with Objectify?

Because the Datastore is shared across multiple versions of an application in App Engine, I'm looking into a way for saving only certain properties of an Entity.
Let's say I have the following class in version 1 of my app:
#Entity
public class ThingA {
#Id private Long id;
private String field1;
private String field2;
}
But in version 2, I changed this class to be:
#Entity
public class ThingA {
#Id private Long id;
private String field1;
private String field2;
private String field3;
}
The problem with saving the whole entity is that every time ThingA is saved on version 1 of the application, it sets "field3" to null.
It would be awesome if there's a way to save only certain fields on ThingA instead of the whole entity.
Thanks
I'm going to answer my own question after Googling a little bit more: The Datastore do not support partial updates to an entity. So that's it.

Which JPA annotation should I use on an AutoPopulatingList?

I have an entity called ReferenceForm which contains an AutoPopulatingList of ReferenceItems. It looks like this:
#Entity
public class ReferenceForm implements Serializable{
private static final long serialVersionUID = -5633788166190438576L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
long id;
#lob
private AutoPopulatingList<ReferenceItem> referenceItems;
}
If I add no annotation at all to the AutoPopulatingList, the field type which hibernate creates is varbinary(255). This causes string truncation errors. To work around this, I used the #lob annotation. This felt questionable at the time, but it worked fine. At this point I was just using HSQLDB.
Now the application needs to run against MSSQL. I have generated the schema using Hibernate, and referenceItems ia an image column on the ReferenceForm table. The items themselves are stored in the ReferenceItem table.
Is #lob an appropriate annotation here?.
EDIT: ReferenceItem looks like this:
#Entity
public class ReferenceItem implements Serializable {
private static final long serialVersionUID = -9077063073733429102L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
long id;
private Title title;
private String firstName;
private String surname;
private String positionHeld;
private String institutionCompany;
#Embedded
private Address address;
#Embedded
private Telephone telephone;
private String email;
private boolean existingReference;
private String fileName;
public ReferenceItem() {
}
...getters and setters
}
SECOND EDIT:
Thanks to Willome for suggesting using #OneToMany. In the end, this is what worked.
//from
#lob
private AutoPopulatingList<ReferenceItem> referenceItems;
//to
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private List<ReferenceItem> referenceItems = new AutoPopulatingList<ReferenceItem>(ReferenceItem.class);
#OneToMany accurately describes the nature of the relationship
Use the interface (List) instead of the implementation when defining the field. See http://docs.jboss.org/hibernate/core/3.3/reference/en/html/collections.html
Define the CascadeType, otherwise this error appears on saving the entity: org.hibernate.TransientObjectException: object references an unsaved transient instance
Make the FetchType EAGER otherwise you cannot load the form in a different transaction: this error appears: failed to lazily initialize a collection of role: ReferenceForm.referenceItems, could not initialize proxy - no Session
You should replace your #Lob annonation with a #OneToMany and replace the AutoPopulatingList with a collection-valued field declared as an interface type (Check out the topic 6.1. Persistent collections on this link http://docs.jboss.org/hibernate/core/3.3/reference/en/html/collections.html.)
//#Lob
#OneToMany(mappedBy = "referenceForm")
private AutoPopulatingList<ReferenceItem> referenceItems; //fail AutoPopulatingList is not an interface
#OneToMany(mappedBy = "referenceForm")
private Set<ReferenceItem> referenceItems; // OK with Set/Collection/List
Thanks to Willome for suggesting using #OneToMany. In the end, this is what worked.
//from
#lob
private AutoPopulatingList<ReferenceItem> referenceItems;
//to
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private List<ReferenceItem> referenceItems = new AutoPopulatingList<ReferenceItem>(ReferenceItem.class);
#OneToMany accurately describes the nature of the relationship
Use the interface (List) instead of the implementation when defining
the field. See
http://docs.jboss.org/hibernate/core/3.3/reference/en/html/collections.html
Define the CascadeType, otherwise this error appears on saving the
entity: org.hibernate.TransientObjectException: object references an
unsaved transient instance
Make the FetchType EAGER otherwise you
cannot load the form in a different transaction: this error appears:
failed to lazily initialize a collection of role:
ReferenceForm.referenceItems, could not initialize proxy - no Session

java.lang.IllegalStateException : Attempting Create Multiple Associations On Variables of Class

first post here, hoping someone could perhaps shed some light on an issue I've been trying to juggle...
As a part of a school project we're attempting to build a interface to display points on a map and paths on a map.
For our first sprint I managed to work out storing/retrieving items using Objectify - it went great!
Now we're trying to extend the functionality for our next spring. Having problems now trying to store an object of type MapPath (note MapPath and MapData, our two data types, both extend class Data). Brief code snippets as follows :
#Entity
public class Data extends JavaScriptObject
{
#Id
Long id;
private String name;
private String dataSet;
...getters and setters
}
#Subclass
public class MapData extends Data implements Serializable{
{
private String name;
private String address;
private String dataSet;
#Embedded
private Coordinate location;
....constructors, getters/setters
}
#Subclass
public class PathData extends Data implements Serializable{
private String name;
private String address;
private String dataSet;
#Embedded
private Coordinate[] path;
...etc
}
Now hopefully I haven't lost you yet. I have a DataService class that basically handles all transactions. I have the following unit test :
#Test
public void storeOnePath(){
PathData pd = new PathData();
pd.setName("hi");
DataService.storeSingleton(pd);
Data d = DataService.getSingleton("hi");
assertEquals(pd,d);
}
The implementation of getSingleton is as follows :
public static void storeSingleton(Data d){
Objectify obj = ObjectifyService.begin();
obj.put(d);
}
JUnit complains:
java.lang.ExceptionInInitializerError
at com.teamrawket.tests.DataTest.storeOnePath(DataTest.java:59)
...<taken out>
Caused by: java.lang.IllegalStateException: Attempting to create multiple associations on class com.teamrawket.server.MapData for name
at com.googlecode.objectify.impl.Transmog$Visitor.addRootSetter(Transmog.java:298)
at com.googlecode.objectify.impl.Transmog$Visitor.visitField(Transmog.java:231)
at com.googlecode.objectify.impl.Transmog$Visitor.visitClass(Transmog.java:134)
at com.googlecode.objectify.impl.Transmog.<init>(Transmog.java:319)
at com.googlecode.objectify.impl.ConcreteEntityMetadata.<init>(ConcreteEntityMetadata.java:75)
at com.googlecode.objectify.impl.Registrar.registerPolymorphicHierarchy(Registrar.java:128)
at com.googlecode.objectify.impl.Registrar.register(Registrar.java:62)
at com.googlecode.objectify.ObjectifyFactory.register(ObjectifyFactory.java:209)
at com.googlecode.objectify.ObjectifyService.register(ObjectifyService.java:38)
at com.teamrawket.server.DataService.<clinit>(DataService.java:20)
... 27 more
What exactly does "attempting to create multiple associations on class ... for name" imply?
Sorry for the long post and any formatting issues that may arise.
You have repeated field names in your subclasses. You should not declare 'name' and 'dataSet' in both superclasses and subclasses; remove these fields from MapData and PathData and you should be fine.
com.teamrawket.server.MapData refers to the fullPath name for your MapData file. The name at the end refers to the field String name in your MapData class. This whole exception tries to tell you that it already contains a reference for that specific fullPath.
I would say there is another object with the same fullPath already registered. It would be helpful to know where line 59 is exactly as that is where the error occured.

Resources