OK, So I am having some issues with getting data from a form to bind to a model class I have.
I have a class Question that basically looks like this:
#Entity
public class Question extends Model {
#Id #Required public int id;
public String title;
public String body;
...methods...
}
So I want to use this as a template for a form for a user to create a question, so I create a static instance (as they do in the samples)
final static Form<Question> question_form = form(Question.class);
So far so good, everything compiles. The problem comes when I actually submit the form:
Form<Question> filled_form = new Form<Question>(Question.class).bindFromRequest();
Here I get the error:
[UnexpectedTypeException: No validator could be found for type: java.lang.Integer]
My thinking on how to proceed is to use a design pattern that goes like this:
1.) Create template classes specifically for Forms, that don't include things like foreign keys, IDs, and information that isn't in a format designed for the user. (i.e. if the Question has a foreign key for Topic, the QuestionForm class would have a String topic field.
2.) Create a methods in the Question model that goes something like getFormForQuestion(Question) and getQuestionForForm(Form<Question>) and then use these methods to do CRUD functions.
So basically the User and controller interact using Forms, and then the Model knows how to take these forms and turn them into entries in the database.
Is this a reasonable way to proceed? Or is there a better way of doing this?
UPDATE:
Seems to be fixed when using #GeneratedValue annotation rather than the #Required annotation, but I am still curious regarding my proposed Form Design pattern.
Also just removing #Required appears to fix the problems. Still looking for comments on the mentioned design pattern!
id field doesn't need any validation, ORM will care about it. Of course you should not place id in form (it shouldn't be edited at all - it's common AUTO_INCREMENT) And better make it Long, just:
#Id
public Long id;
Related
I am developing a simple dictionary RESTful API with Spring-mvc. There are two related entities:
public class Word {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String word;
#ManyToOne(fetch=FetchType.EAGER)
#JoinColumn(name="LANGUAGE_ID", insertable=false, updatable=false)
private Language language;
}
Based on the code above the related entity is Language.
Issue: I would like to implement the CREATE operation on the Word entity with POST request. The implementation is not difficult, but I did find at least two solution candidates in relation to the POST request URL and JSON request body:
Solution Candicate I: directly insert with JSON body request. The JSON body contain the nested JSON object - Language, something like
{id:1, word:"hello", Language: {id:1, language:"English"}}
reference: Spring: Save object with foreign keys with a POST request
Solution Candidate II: get the referenced Language id through the POST request URL, say something like
POST http://localhost:8080/rest/language/1/words
As such, there is no Language reference at all in the JSON POST request body.
reference: https://www.youtube.com/watch?v=_Jnu_jHfQbM
I have 2 questions:
Question 1: among these two solution candidates, which is the better one, or say professional standard solution? or is there any other solution?
Question 2: as to both the given solution candidate, in any case we need to retrieve the referenced Language POJO at least in the corresponding controller class. But from the perspective of OO-design principle, this way seems to be tightly coupled with the controller, so I am thinking that should we decouple this retrieval behavior somewhere else than in controller? for instance in the service layer. But is this the professional way? and we need to have a corresponding DTO?
In my opinion the data which should be saved has to be nested in the body. Spring could map the json data directly into an object and you don't have to set it from parameter to another model class.
And i would create separate model classes for your entities. So the controller fills the data to the model classes and give them to a service. Then the service maps the model classes to entities. After that they could be stored via repositories.
Example:
#Controller
public class RestController {
#Autowired
RestService restService;
#PostMapping(value="/")
public void saveVariable( #RequestBody TestModel testModel ) {
testService.saveTest( testModel );
}
}
#Service
public class RestService {
#Autowired
TestRespository testRepository;
public void saveTest( TestModel testModel ) {
TestEntity testEntity = new TestEntity();
//some mapping from testModel to testEntity
testRepository.save( testEntity );
}
}
Assuming that words belong to a language, I would design it as following:
POST /api/languages/en/words HTTP/1.1
Host: localhost:8080
Content-Type: application/json
{
"word": "hello"
}
Where a representation of a word (a JSON document, for example) is sent in the request payload to a URL that represents a hierarchy (a language has words).
You also could use two-letter codes to identify the languages, since it's the way clearer than numeric values. In the above example, en means English.
I advise you to avoid exposing persistence entities in your REST API and use DTOs instead. Your REST resources representations don't need to have the same attributes as the persistence objects.
Keep your REST controllers as lean as possible and keep your service layer focused on business rules.
I would like to annotate a method with Spring Data #Id but it only works with fields, despite the fact that the annotation can be used on methods.
Is there a way to use #Id on methods too?
I'm using Spring Boot 1.3.0.RELEASE
EDIT
Actually I have this interface that will have an instance being created at runtime.
import org.springframework.data.annotation.Id;
#Document(indexName = "index", type = "document")
public interface Document {
#Id
Integer getId();
}
And this repository.
public interface DocumentRepository extends ElasticsearchCrudRepository<Document, Integer> {
}
Problem is that SimpleElasticsearchPersistentProperty from spring-data-elasticsearch 1.3.0.RELEASE always look for fields:
https://github.com/spring-projects/spring-data-elasticsearch/blob/1.3.0.RELEASE/src/main/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentProperty.java
That way if I create an asbtract class instead and put #Id on a field, everything works fine.
The #Id annotation does work on properties, i.e. you can put it on getters, setters or fields. If this does not work something is wrong. Possible reasons are:
the names don't fit the property conventions
you are using the wrong #Id annotation
It does not work on arbitrary methods because Spring Data wouldn't be able to determine a name for that non-property, which in turn is required for many features.
I have a class defined as:
class Person {
public int age;
public String firstName;
}
Note that I use camel case for the field names. Also, I know that I could have generated getters and setters but I tend to not do that for simple domain objects.
When I deserialize a JSON or XML response in my REST API, it should spit out:
<Person><Age>11</Age><FirstName>Johnson</FirstName></Person>
You will notice that the first letter is upper-cased.
I could use, for example, #JsonPoperty("FirstName") on my POJO to get the output the way I need it, but this doesn't scale when there are too many fields. I'd like to use a custom property naming strategy (as described in How To Use Property Naming Strategy In Jackson). But instead of configuring an ObjectMapper, I was wondering if its possible to specify a naming strategy using annotations?
Thanks
I am very new to GWT.
I am using ext-gwt widgets.
I found many places in my office code containing like,
class A extends BaseModel{
private UserAccountDetailsDto userAccountDetailsDto = null;
//SETTER & GETTER IN BASEMODEL WAY
}
Also, the DTO reference is unused.
public class UserAccountDetailsDto implements Serializable{
private Long userId=null;
private String userName=null;
private String userAccount=null;
private String userPermissions=null;
//NORMAL SETTER & GETTER
}
Now, I am able to get the result from GWT Server side Code and things Work fine, but when I comment the DTO reference inside the class A, I am not getting any Result.
Please explain me the need of that.
Thanks
Well the problem is in implementation of GXT BaseModel and GWT-RPC serialization.
BaseModel is based around special GXT map, RpcMap. This map has defined special serialization rules, which let's avoid RPC type explosion, but as side effect, only some simple types stored in map will be serialized. E.g. you can put any type inside the map, but if you serialize/deserialize it, only values of type Integer, String ,Double,Byte, Float and Short (and arrays of this types) will be present. So the meaning behind putting reference to the DTO inside BaseModel, is to tell GWT-RPC that this type is also have to be serialized.
Detailed explanation
Basically GWT-RPC works like this:
When you define an interface for service, GWT-RPC analyzes all the classes used in parameters/ return type, to create serializers/deserializers. If you return something like Map<Object,Object> from your service, GWT-RPC will have to create a serializer for each class which implements Map and Serializable interfaces, but also it will generate serializers for each class which implements Serializable. In the end it is quite a bad situation, because the size of your compiled js file will be much biggger. This situation is called GWT-RPC type explosion.
So, in the BaseModel, all values are stored in RpcMap. And RpcMap has custom written serializer (RpcMap_CustomFieldSerializer you can see it's code if you interested how to create such things), so it doesn't cause the problem described above. But since it has custom serializer GWT dosn't know which custom class have been put inside RpcMap, and it doesn't generate serializers for them. So when you put some field into your BaseModel class, gwt knows that it might need to be able to serialize this class, so it will generate all the required stuff for this class.
Porting GXT2 Application code using BaseModel to GXT3 Model is uphill task. It would be more or less completely rewrite on model side with ModelProviders from GXT3 providing some flexibility. Any code that relies on Model's events, store, record etc are in for a rewrite.
I've been looking around for an answer to this, which I can't believe hasn't been asked before, but with no luck I'm attempting here.
I have a signup form which differs slightly based upon what type of participant the requester is. While writing tests for the solution, I realized that all actions did the same things, so I'm attempting to combine the actions into one using a strategy pattern.
public abstract class BaseForm { common properties and methods }
public class Form1 : BaseForm { unique properties and overrides }
....
public class FormX : BaseForm { unique properties and overrides... in all about 5 forms }
Here is the combined action:
[ModelStateToTempData, HttpPost]
public ActionResult Signup(int id, FormCollection collection)
{
uiWrapper= this.uiWrapperCollection.SingleOrDefault(w => w.CanHandle(collection));
// nullcheck on uiWrapper, redirect if null
var /*BaseForm*/ form = uiWrapper.GetForm(); // Returns FormX corresponding to collection.
this.TryUpdateModel(form, collection.ToValueProvider()); // Here is the problem
form.Validate(this.ModelState); // Multi-Property validation unique to some forms.
if (!this.ModelState.IsValid)
return this.RedirectToAction(c => c.Signup(id));
this.Logic.Save(form.ToDomainClass());
return this.RedirectToAction(c => c.SignupComplete());
}
The problem I'm having is that TryUpdateModel binds only the common properties found in BaseForm. My previous code used public ActionResult FormName(int id, FormX form) which bound properly. However, I did some testing and discovered that if I replace var form with FormX form the form binds and everything works, but I'm back to one action per form type.
I'm hoping to find a way to get this to bind properly. form.GetType() returns the proper non-base class of the form, but I'm not sure of how to grab the constructor, instantiate a class, and then throw that into TryUpdateModel. I know that the other possibility is a custom ModelBinder, but I don't see a way of creating one without running into the same FormBase problem.
Any ideas or suggestions of where to look?
I was trying to do something similar to Linq, I was trying to create a class that would inherit some standard fields (ID, etc). I found that the default Linq engine would only use fields from the instantiated class, not from any inherited classes or interfaces.
To construct a Type simply use code like:
var form = Activator.CreateInstance(uiWrapper.GetForm());
I figured it out!
Erik's answer wasn't the solution, but for some reason it made me think of the solution.
What I really want form to be is a dynamic type. If I change this line:
dynamic form = uiWrapper.GetForm();
Everything works :)
On top of that, logic.Save(form.ToDomainClass()) also goes directly to Save(DomainTypeOfForm) rather than Save(BaseDomainForm) so I can avoid the headache there as well. I knew that once I figured out the problem here I could apply the answer in my logic class as well.