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
Related
I have the following #Builder - annotated class:
#Data
#Builder(access = AccessLevel.PUBLIC)
#Entity
public class LiteProduct
{
// Minimal information required by our application.
#Id
private Long id; // Unique
private String name;
private Long costInCents;
private String type;
// Model the product types as a Hash Set in case we end up with several
// and need fast retrieval.
public final static Set<String> PRODUCT_TYPES = new HashSet<>
(Arrays.asList("flower", "topical", "vaporizer", "edible", "pet"));
// Have to allow creation of products without args for Entities.
public LiteProduct()
{
}
public LiteProduct(#NonNull final Long id, #NonNull final String name,
#NonNull final String type, #NonNull final Long costInCents)
{
if(!PRODUCT_TYPES.contains(type))
{
throw new InvalidProductTypeException(type);
}
this.name = name;
this.id = id;
this.costInCents = costInCents;
}
Whenever I want to use the builder class that Lombok is purported to give me, despite the fact that the IDE seems to detect it just fine:
I get a compile-time error about its visibility:
I have looked at some workarounds such as this or this, and they all seem to imply that my problem ought to already be solved automatically and that Lombok by default produces public Builder classes. This does not seem to be implied from my output, and does not happen even after I put the parameter access=AccessLevel.PUBLIC in my #Builder annotation in LiteProduct. Any ideas? Is there something wrong with the fact that this class is also an #Entity? Something else I'm not detecting?
// Edit: I determined that when I move the class in the same package as the one I am calling the builder pattern from, it works just fine. This is not an #Entity issue, but a package visibility issue which based on what I'm reading should not be there.
The problem was that I was using the following line of code to create an instance of LiteProduct:
return new LiteProduct.builder().build();
instead of:
return LiteProduct.builder().build();
which is what the #Builder annotation allows you to do. Clearly builder() is like a factory method for Builders that already calls new for you.
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' :)
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'm trying to create a PK class for a JDO Entity named Item. It's was soo simple with JPA, but now im practicing JDO. I'm using anotation configuration and this is how the two classes look like:
#PersistenceCapable(table="ITEM",identityType = IdentityType.APPLICATION,
objectIdClass = ItemPK.class,schema="mgr")
public class Item {
#PrimaryKey
#Persistent(column="code")
private long code; //WHY public?
#PrimaryKey
#Persistent(column="producer")
private String producer;
#PrimaryKey
#Embedded
private ItemPK id;
#Persistent(column="price")
private double price;
#Persistent(column="name")
private String name;
#Persistent(column="description")
private String description;
[... getters/setters...]
}
I want the ItemPK class to be used as a Primary Key class with thoose two columns (code,producer). So this is how the class looks like:
#EmbeddedOnly
#PersistenceCapable(embeddedOnly="true",identityType=IdentityType.APPLICATION)
public class ItemPK implements Serializable{
#Persistent
#PrimaryKey
public long code;
#Persistent
#PrimaryKey
public String producer;
#Override
public String toString() {
return code+"_"+producer;
}
#Override
public int hashCode() {
[...Eclipse autogenerated...]
}
#Override
public boolean equals(Object obj) {
[...Eclipse autogenerated...]
}
}
What I do get after trying to run the code:
[...Caused by]
Nested Throwables StackTrace:
Class pl.edu.pw.mini.entity.jdo.Item has been specified with an object-id class pl.edu.pw.mini.entity.jdo.ItemPK which has a field jdoStateManager which isnt Serializable. All non static fields of an objectId class must be serializable.
org.datanucleus.metadata.InvalidPrimaryKeyException: Class pl.edu.pw.mini.entity.jdo.Item has been specified with an object-id class pl.edu.pw.mini.entity.jdo.ItemPK which has a field jdoStateManager which isnt Serializable. All non static fields of an objectId class must be serializable.
As I understand the enhancer adds jdoStateManager to a ItemPK, ad it is not Serializable. But as ItemPK is embedded, either it should not get the jdoStateManager, or JDO should know the difference between jdoStateManager and a regular field. What am I doing wrong to get an embedded class for a 2-column Primary Key
I have no Idea how to make this thing work, can anyone help me, and tell me what am I doing wrong here?
The docs define perfectly well how to do that
http://www.datanucleus.org/products/accessplatform_3_1/jdo/orm/compound_identity.html
and it doesn't involve use of #Embedded
I have a problem trying to map an inheritance tree. A simplified version of my model is like this:
#MappedSuperclass
#Embeddable
public class BaseEmbedded implements Serializable {
#Column(name="BE_FIELD")
private String beField;
// Getters and setters follow
}
#MappedSuperclass
#Embeddable
public class DerivedEmbedded extends BaseEmbedded {
#Column(name="DE_FIELD")
private String deField;
// Getters and setters follow
}
#MappedSuperclass
public abstract class BaseClass implements Serializable {
#Embedded
protected BaseEmbedded embedded;
public BaseClass() {
this.embedded = new BaseEmbedded();
}
// Getters and setters follow
}
#Entity
#Table(name="MYTABLE")
#Inheritance(strategy=InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(name="TYPE", discriminatorType=DiscriminatorType.STRING)
public class DerivedClass extends BaseClass {
#Id
#Column(name="ID", nullable=false)
private Long id;
#Column(name="TYPE", nullable=false, insertable=false, updatable=false)
private String type;
public DerivedClass() {
this.embedded = new DerivedClass();
}
// Getters and setters follow
}
#Entity
#DiscriminatorValue("A")
public class DerivedClassA extends DerivedClass {
#Embeddable
public static NestedClassA extends DerivedEmbedded {
#Column(name="FIELD_CLASS_A")
private String fieldClassA;
}
public DerivedClassA() {
this.embedded = new NestedClassA();
}
// Getters and setters follow
}
#Entity
#DiscriminatorValue("B")
public class DerivedClassB extends DerivedClass {
#Embeddable
public static NestedClassB extends DerivedEmbedded {
#Column(name="FIELD_CLASS_B")
private String fieldClassB;
}
public DerivedClassB() {
this.embedded = new NestedClassB();
}
// Getters and setters follow
}
At Java level, this model is working fine, and I believe is the appropriate one. My problem comes up when it's time to persist an object.
At runtime, I can create an object which could be an instance of DerivedClass, DerivedClassA or DerivedClassB. As you can see, each one of the derived classes introduces a new field which only makes sense for that specific derived class. All the classes share the same physical table in the database. If I persist an object of type DerivedClass, I expect fields BE_FIELD, DE_FIELD, ID and TYPE to be persisted with their values and the remaining fields to be null. If I persist an object of type DerivedClass A, I expect those same fields plus the FIELD_CLASS_A field to be persisted with their values and field FIELD_CLASS_B to be null. Something equivalent for an object of type DerivedClassB.
Since the #Embedded annotation is at the BaseClass only, Hibernate is only persisting the fields up to that level in the tree. I don't know how to tell Hibernate that I want to persist up to the appropriate level in the tree, depending on the actual type of the embedded property.
I cannot have another #Embedded property in the subclasses since this would duplicate data that is already present in the superclass and would also break the Java model.
I cannot declare the embedded property to be of a more specific type either, since it's only at runtime when the actual object is created and I don't have a single branch in the hierarchy.
Is it possible to solve my problem? Or should I resignate myself to accept that there is no way to persist the Java model as it is?
Any help will be greatly appreciated.
Wow. This is the simplified version? I assume that the behavior that you are seeing is that BaseEmbedded field is persisted but not the FIELD_CLASS_A or B?
The problem is that when Hibernate maps the DerivedClassA and B classes, it reflects and sees the embedded field as a BaseEmbedded class. Just because you then persist an object with the embedded field being a NestedClass, the mapping has already been done and the FIELD_CLASS_A and B are never referenced.
What you need to do is to get rid of the NestedClass* and embedded field and instead have the fieldClassA and B be normal members of DerivedClassA and B. Then add add a name field to the #Entity which will put them both in the same table I believe. This will allow you to collapse/simplify your class hierarchy a lot further.
See: http://docs.jboss.org/hibernate/stable/annotations/reference/en/html_single/#d0e1168
#Entity(name = "DerivedClass")
#DiscriminatorValue("A")
public class DerivedClassA extends DerivedClass {
#Column(name="FIELD_CLASS_A")
private String fieldClassA;
...
#Entity(name = "DerivedClass")
#DiscriminatorValue("B")
public class DerivedClassB extends DerivedClass {
#Column(name="FIELD_CLASS_B")
private String fieldClassB;
...