I have a simple entity called Game. I want to allow my users to edit multiple of these entities at once. Therefore I need a form that contains multiple Game Entities.
The problem: When the form is submitted and I invoke hasErrors() my custom ad-hoc validate method in the Game entities is never called. Only the validations marked by annotations are checked and produce errors when they are invalid.
This is the Game Entity:
#Entity
public class Game extends Model {
#Id
public Long id;
#ManyToOne
#Constraints.Required
public Team team1;
#ManyToOne
#Constraints.Required
public Team team2;
//the validate method does not get called
public String validate()
{
System.out.println("Validating the Game Entity.");
if(team1.id == team2.id)
return "You have to choose two different teams!";
return null;
}
public static Model.Finder<Long,Game> find = new Model.Finder<Long,Game>(Long.class, Game.class);
}
This is the Form that contains multiple Game Entities.
public class GameForm {
#Valid
public List<Game> games;
public GameForm()
{
games = new ArrayList<Game>();
}
}
This is the controller method.
public static Result save()
{
Form<GameForm> gameForm = form(GameForm.class).bindFromRequest();
if(gameForm.hasErrors())
return badRequest(create.render(gameForm));
return redirect(
routes.Games.index()
);
}
The docs say that ad-hoc validation only works on the "top" object.
http://www.playframework.com/documentation/2.2.x/JavaForms
For your Form this is probably List, not Game.
Related
I have two functions to encrypt and decrypt data.
My current code is as below. I have entity class, DTO class, repository and service class.
The name need to be encrypted before save to database and to be decrypted when retrieve from database.
Lets say I have 10 different entity classes need to do the encryption and decryption data, I need to add the encryption and decryption function to each service class as below codes.
Is there any way to do all the encryption and decryption data in one service class for all the entity? like overriding the Get and Set method in entity? Anyone can advice? Thanks a lot.
#Entity
#Getter
#Setter
public class Customer {
private Long id;
private String name;
private String contact;
}
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
public class CustomerDTO {
private String name;
}
#Repository
public interface CustomerRepository extends JpaRepository<Customer, Long>{
}
#Service
public class CustomerService {
#Autowired
private CustomerRepository customerRepository;
#Autowired
private EncrytionService encrytionService;
public void save(String name){
Customer customer = new Customer();
customer.setName(encrytionService.doEncrypt(name));
customerRepository.save(customer);
}
public CustomerDTO getCustomer(Long customerId) {
Customer customer = customerRepository.findById(customerId);
CustomerDTO dto = new CustomerDTO();
dto.setName(encrytionService.doDecrypt(customer.getName()));
return dto;
}
}
Not sure there is a way to do that easily (kinda out-of-the-box way), but maybe you could try to implement something yourself using JPA lifecycle events and EntityListener.
For example:
// this is going to be our EntityListener
public class SensitiveDataListener {
#PrePersist
void beforeAnyPersist(Customer customer) {
// encrypt what you need and set
// e.g. customer.setName(encrytionService.doEncrypt(customer.getName()));
}
// after an entity has been loaded
#PostLoad
void afterLoad(Customer customer) {
// decrypt what you need
}
}
// and this is how you add it to your entity
#EntityListeners(SensitiveDataListener.class)
#Entity
public class Customer {
//...
}
A good question here would be - ok I have multiple entities, what do I do - create multiple **Listener classes? In general, no. Your listener can "handle" multiple entities, but how to make it happen - depends on what you need - for instance, if you need to encrypt/decrypt different fields in different entity that's one case, and if you need encrypt/decrypt let's say name and you have this field in different entities, that would be another case and another solution. Also, you might want to encrypt everything and again that would be a different solution because it is yet another use case.
If it is the same field you could probably "unify" you entities (but keep in mind sometimes it is not a good idea when your entities implement some interfaces):
public interface Sensitive {
void setName(final Date date);
}
#EntityListeners(SensitiveDataListener.class)
#Entity
public class Entity1 implements Sensitive {
// override setName
}
#EntityListeners(SensitiveDataListener.class)
#Entity
public class Entity2 implements Sensitive {
// override setName
}
// but then your SensitiveDataListener will look like this
public class SensitiveDataListener {
#PrePersist
void beforeAnyPersist(Sensitive entity) {
// encrypt what you need and set
// e.g. entity.setName(encrytionService.doEncrypt(entity.getName()));
}
// after an entity has been loaded
#PostLoad
void afterLoad(Sensitive entity) {
// decrypt what you need
}
}
Maybe you could also use AttributeConverter, assuming your field is String and encoded value is also String you could create converter which will encode/decode your stuff, but then you need to add it to every field (in every entity) you want to encode.
Something like this:
#Convert(converter = MyAttributeConverter.class)
private String name; // this is entity field
I’m trying to create linked list of nodes with CURRENT/PREVIOUS relation similar to the picture below.
I'm not sure if my solution is the right way to handle this scenario, but to achieve that I created two nodes with a single method to populate new messages as below:
#Builder
#Data
#NoArgsConstructor
public class Person {
#Id
#GeneratedValue
private Long id;
private String name;
#Relationship(type = "LATEST")
private Message message;
void newMessage(Message newMessage) {
newMessage.setPrevious(message);
message = newMessage;
}
}
#Builder
#Data
#NoArgsConstructor
public class Message {
#Id
#GeneratedValue
private Long id;
private String text;
#Relationship(type = "PREVIOUS")
private Message previous;
}
I also created a sample code to test this solution:
#SpringBootApplication
public class NewsFeedApplication {
public static void main(String[] args) {
SpringApplication.run(NewsFeedApplication.class, args);
}
#Bean
CommandLineRunner init(PersonRepository personRepository) {
return args -> {
Person personToAdd1 = Person.builder().name("John").build();
personToAdd1.newMessage(Message.builder().text("first message").build());
personToAdd1.newMessage(Message.builder().text("second message").build());
personToAdd1.newMessage(Message.builder().text("third message").build());
personRepository.save(personToAdd1);
personToAdd1.newMessage(Message.builder().text("New message.").build());
personRepository.save(personToAdd1);
};
}
}
I feel like I'm close, but I don't know how to reset the previous CURRENT relation and my solution produces output as:
So the question is:
If my approach is okay, how could I remove previous CURRENT relation.
If this approach is wrong, how could I implement linked list with CURRENT/PREVIOUS relations for nodes correctly.
I found the missing puzzle, i.e. detaching the supplier relation. I don't know why I assumed in advance that this relation should be deleted automatically by the spring data repository "save" method.
Working solution:
public interface PersonRepository extends Neo4jRepository<Supplier, Long> {
#Query("MATCH (n:Person {name: $name})-[r:LATEST]->() DELETE r")
void detachLatestFromPerson(String name);
}
void newMessage(PersonRepository personRepository, Message newMessage) {
personRepository.detachLatestFromPerson(name);
newMessage.setPrevious(message);
message = newMessage;
}
PS. I still have doubts, as I'm not sure if that's a good approach to handle this scenario, so if you know a better solution, go ahead and post it, we can always swap the 'best answer' :)
Hi say I have sample bean called car and I want to redefine its validation sequence:
#GroupSequenceProvider(value = CarSequenceProvider.class)
public class Car{
#NotNull(groups = {groupOne.class})
private Boolean isGood;
#Valid
private List<Driver> drivers;
// getter/setter
}
this is my driver class
public class Driver{
#NotEmpty(groups = {groupTwo.class})
private List<String> skills;
//getter/setter
}
and here goes my sequence provider:
public class CarSequenceProvider implements DefaultGroupSequenceProvider<Car>{
#Override
public List<Class<?>> getValidationGroups(Car car) {
List<Class<?>> sequence = new ArrayList<Class<?>>();
sequence.add(Car.class);
sequence.add(groupOne.class);
if(car != null && car.IsGood()){
sequence.add(groupTwo.class);
}
}
Basically I only want All drivers skills not to be empty if the car is good. What is happening right now is that #notEmpty never gets called because my sequence redefinition is not cascaded to Driver List. Is it possible to make it cascade then?
Thank you so much
Here #ConvertGroup comes into play which allows you during cascaded
validation to use a different group than the originally requested one.
Is that annotation you tried
Source: example-group-conversion-dedault-to-driver-checks
I am working on a Spring-MVC application in which depending upon the mode set by the user, I have to return a List of either Object1 or Object2. Ideally, I can create two controller methods and send the List appropriately, but I would like to know is there any way, I can send any type of List in that Controller method.
Controller method :
#PreAuthorize("hasRole('ROLE_USER')")
#RequestMapping(value = "/findnotebydays/{days}/{canvasid}/{mode}")
public #ResponseBody List<Inotes> findNotesByDays(#PathVariable("days")int days, #PathVariable("canvasid")int canvasid,
#PathVariable("mode")boolean mode ){
if(!mode){
return this.groupNotesService.findGroupNotesByDays(days,canvasid);
} else {
return this.notesService.findNotesByDays(days,canvasid);
}
}
Basically, if mode is false, I want to return List<GroupNotes> and if mode is true, I would like to return List<Notes>. My naive approach that I thought I can just say it is an Object and return, but doesn't seem to work. Kindly let me know what I can do. Thanks a lot. :-)
Update
GroupNotes model class :
#Entity
#Table(name="groupnotes")
public class GroupNotes implements Inotes{
#Id
#Column(name="mnoteid")
#GeneratedValue(strategy = GenerationType.SEQUENCE,generator = "mnote_gen")
#SequenceGenerator(name = "mnote_gen",sequenceName = "mnote_seq")
#org.hibernate.annotations.Index(name = "mnoticesidindex")
private int mnoticesid;
#Column(name = "mnotetext")
private String mnotetext;
//Other variables, getters, setters ignored
}
Notes model class :
#Entity
#Table(name="note")
public class Notes implements Inotes{
#Id
#Column(name="noteid")
#GeneratedValue(strategy = GenerationType.SEQUENCE,generator = "note_gen")
#SequenceGenerator(name = "note_gen",sequenceName = "note_seq")
#org.hibernate.annotations.Index(name = "noteidindex")
private int noticesid;
#Column(name = "notetext")
private String notetext;
//Other variables, getters, setters ignored
}
Interface Inotes :
package com.journaldev.spring.model;
public interface Inotes {
}
Following the clean coder style, if you have to pass a boolean to a method, that method actually does two different things, and you want a method to do only one thing.
I would just make two controller actions, it is much clearer to the user and to the maintainer of the code later on.
You should probably use a common interface shared by both classes.
Declaring an interface like, for instance:
public interface INotes{
}
public class GroupNotes implements INotes{...}
public class Notes implements INotes{...}
Your code would become:
#PreAuthorize("hasRole('ROLE_USER')")
#RequestMapping(value = "/findnotebydays/{days}/{canvasid}/{mode}")
public #ResponseBody List<INotes> findNotesByDays(#PathVariable("days")int days, #PathVariable("canvasid")int canvasid,
#PathVariable("mode")boolean mode ){
if(!mode){
return this.groupNotesService.findGroupNotesByDays(days,canvasid);
} else {
return this.notesService.findNotesByDays(days,canvasid);
}
}
Another simpler solution would be just returning List (or List<?> for compliance) but this approach is more appropriated.
Considering Notes and GroupNotes are both implementing the Note interface (for example), you could always return List<Note>.
I am not sure what the best practice is for dealing with collection/lookup tables/in RequestFactory.
For example if I have following two Domain objects:
#Entity
public class Experiment {
private Long id;
private String name;
#ManyToOne(cascade={CascadeType.PERSIST,CascadeType.MERGE})
private UnitOfMeasure unitOfMeasure;
public Experiment() { }
public String getName() {
return name;
}
public Long getId() {
return id;
}
public void setName(String name) {
this.name = name;
}
public UnitOfMeasure getUnitOfMeasure() {
return unitOfMeasure;
}
public void setUnitOfMeasure(UnitOfMeasure unitOfMeasure) {
this.unitOfMeasure = unitOfMeasure;
}
}
#Entity
public class UnitOfMeasure {
private Long id;
private String unit_type;
public UnitOfMeasure() { }
public String getUnitType() {
return unit_type;
}
public Long getId() {
return id;
}
public void setUnitType(String unitType) {
this.unit_type = unitType;
}
}
This is a normal unidirectional 1:n realtionship between Experiment and UnitOfMeasure using a ForeignKey in the Experiment table.
I have a limited amount of different UnitOfMeasure instances which usually don't change.
The web-app provides a view where the user can change some properties of the Experiment instance. The view uses the Editor framework. For changing the UnitOfMeasure of a specific Experiment I use a ValueListBox and render the unit_type property.
Because the list of available UnitOfMeasure instances is static I use AutoBeanFactory to create a json string which I put into the HTML host page and during application start I parse it (same thing for all other collection like table values) and store them in a Singleton class instance (AppData) which I pass to `setAcceptableValues``.
Currently I derive UnitOfMeasureProxy from EntityProxy but in order to decode/encode it with AutoBeanFactory I have to annotate the Factory with EntityProxyCategory. I somehow suspect that a ValueProxy would be a better fit.
However with a ValueProxy when I change the UnitOfMeasure of a specific Experiment the entire ValueProxy instance is transmitted over the wire.
From a database point of view however only changing the value for the foreignkey in the Experiment table is required.
So what is the best practice (ValueProxy vs EntityProxy) for collection like tables and child values respectively?
In many cases, references to other entities are best modelled using their IDs rather than the EntityProxys themselves (it's debatable, but I think it's also true for server-side code, or actually any code that crosses unit-of-work boundaries –JPA EntityManager lifetime, Hibernate session, etc.–)
BTW, the proper way to serialize RequestFactory proxies is to use a ProxySerializer.
Make sure you use GWT 2.5.0-rc1 though if you have lists of ValueProxys (see issue 6961)