I am using JHipster 3.3. In the generated "entity"-dialog.html, I noticed the tag jhi-alert-error element will display server validation error so for example if a field is mandatory as specified in entity JPA class like
#NotNull
private String name;
Then error message for that field will be returned after clicking the Submit button if value of the field is empty.
So questions:
How is jhi-alert-error implemented? I can't seem to see its implementation
I tried tweaking JPA annotation to make a field unique BUT this time no error message will be displayed in jhi-alert-error if I break the unique constraint by adding 2 records having the same value for the field,
E.g.
// note 'unique=true' below
#NotNull
#Column(name = "name", unique=true)
private String name;
or
#Table(name="Module", uniqueConstraints = #UniqueConstraint(columnNames = "Name"))
public Class Module implements Serializable { ...
So how would I go about implementing my own server side form validation so error messages will be displayed in jhi-alert-error when the unique constraint of a field is broken after clicking the Submit button?
Thanks in advance,
I'm using a slightly older version of jhipster (2.26), so there could be some differences in the code. To answer your first question the jhi-alert-error is a custom Angular directive, have a look at the alert.directive.js file and the jhAlertError directive (should appear after the jhAlert directive). The directive expects the httpResponse.data object to be the ErrorDTO server side object.
To add custom error messages, you need to return an ErrorDTO object and the directive will display the message. To do this you need to throw an exception and ensure that the spring AOP - ExceptionTranslator is configured to catch it. If you don't want to create new custom Exceptions, you can use the CustomParameterizedException:
#RequestMapping(value = "/pizzas",
method = RequestMethod.POST,
produces = MediaType.APPLICATION_JSON_VALUE)
#Timed
public ResponseEntity<Pizza> create(#RequestBody Pizza pizza) throws URISyntaxException {
if(pizza.isDisgusting()){
throw new CustomParameterizedException("Sorry, your pizza recipe is horrible");
}
log.debug("REST request to save Pizza : {}", pizza);
if (pizza.getId() != null) {
return ResponseEntity.badRequest().header("Failure", "A new pizza cannot already have an ID").body(null);
}
Pizza result = pizzaRepository.save(pizza);
return ResponseEntity.created(new URI("/api/pizzas/" + pizza.getId())).body(result);
}
Related
In contrast to attributes with the persistence type set to property that are persisted in a database, Dynamic Attributes have non-persistent values
SAP Hybris Commerce allows for a non-persistent kind of attribute referred to as a jalo attribute or jalo-only attribute.
Jalo attributes are deprecated and replaced by Dynamic Attributes.
I still see Hybris still using both.
So,What is the difference between of each?
What is the purpose of each?
Thanks
Actually half of the answer is in your question, Both Jalo and Dynamic attributes are used to create non-persisted attributes for items in Hybris.
But why do we need non-persisted attribute?
As you may know Items class in Hybris are generated using ant command so there is no way to add business logic manually to the item (because every time i run ant command a new item will be generated and my logic will be erased too)
I will give you an example :
//generated item
class PersonModel {
//persisted attributes
String firstname;
String lastName;
//non-persisted attribute = calculated attribute
String getFullName() {
return firstname + " " + lastname;
}
}
We all agree that fullName should not be persisted in the database, so let's assume that getFullName is added manually, then as i explained before if we run ant clean all command PersonModel will be re-generated again and getFullName() will be erased too.
So this what Jalo attribute created for, actually Jalo items are generated only once and will never be removed (it can be removed manually) so we can add all calculated attributes in Jalo item without fear of being erased.
//generated item is going to
//be re-generated after each ant clean all
class PersonModel {
//persisted attributes
String firstname;
String lastName;
}
//Jalo item will be generated once
//and will never be removed after that
class PersonJalo {
//non-persisted attribute = calculated attribute
String getFullName() {
return firstname + " " + lastname;
}
}
Jalo attribute is deprecated now and replaced by dynamic attribute, so we should never use jalo any more and use dynamic attribute instead.
i got error in my codes like this :
javax.persistence.PersistenceException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.DatabaseException Internal Exception: java.sql.SQLSyntaxErrorException: Syntax error: Encountered ":" at line 1, column 42. Error Code: -1 Call: select userLevelId from USERS where id = :id Query: DataReadQuery(sql="select userLevelId from USERS where id = :id ")
and my code :
public String cek() { if (tmp.equals(tmp2)) {
y =1;
level = getItems().toString(); }
.....
.....
}
public List<Users> getItems() {
if (y.equals(1)) {
y=0;
tmp = tmp.trim();
return em.createNativeQuery("select userLevelId from USERS where id = :id")
.setParameter("id", tmp).getResultList(); }
}
so where's my fault ?
can anyone help me ?
thx b4
Main Problem
Native queries don't use named parameter syntax (:id). Use prepared statement syntax with the ?. Then use. setParameter( indexOf?, value ) . For example
...("select userLevelId from USERS where id = ?")
...setParameter(1, tmp)
Other Notes
Don't do your querying in the getter if the getter is part of the property binding. For instance if you have List<User> items as a bean property, don't do any business logic or in your case querying in the getter. The getter may be called for a few number of reason, apart from what you expect. Instead you can initialize it in a #PostConstruct method or in your constructor. If you need to update the list, have a listener method that will update it, and directly call that method
A common practice is to separate the business layer and web layer (the managed bean). The business layer can be an EJB in which you inject into the managed bean
I have a business requirement to only send permissioned properties in our response payload. For instance, our response DTO may have several properties, and one of them is SSN. If the user doesn't have permissions to view the SSN then I would never want it to be in the Json response. The second requirement is that we send null values if the client has permissions to view or change the property. Because of the second requirement setting the properties that the user cannot view to null will not work. I have to still return null values.
I have a solution that will work. I create an expandoObject by reflecting through my DTO and add only the properties that I need. This is working in my tests.
I have looked at implementing ITextSerializer. I could use that and wrap my response DTO in another object that would have a list of properties to skip. Then I could roll my own SerializeToString() and SerializeToStream(). I don't really see any other ways at this point. I can't use the JsConfig and make a SerializeFn because the properties to skip would change with each request.
So I think that implementing ITextSerializer is a good option. Are there any good examples of this getting implemented? I would really like to use all the hard work that was already done in the serializer and take advantage of the great performance. I think that in an ideal world I would just need to add a check in the WriteType.WriteProperties() to look and the property is one to write, but that is internal and really, most of them are so I can't really take advantage of them.
If someone has some insight please let me know! Maybe I am making the implementation of ITextSerialzer a lot harder that it really is?
Thanks!
Pull request #359 added the property "ExcludePropertyReference" to the JsConfig and the JsConfigScope. You can now exclude references in scope like I needed to.
I would be hesitant to write my own Serializer. I would try to find solutions that you can plug in into the existing ServiceStack code. That way you will have to worry less about updating dlls and breaking changes.
One potential solution would be decorating your properties with a Custom Attributes that you could reflect upon and obscure the property values. This could be done in the Service before Serialization even happens. This would still include values that they user does not have permission to see but I would argue that if you null those properties out they won't even be serialized by JSON anyways. If you keep all the properties the same they you will keep the benefits of strong typed DTOs.
Here is some hacky code I quickly came up with to demonstrate this. I would move this into a plugin and make the reflection faster with some sort of property caching but I think you will get the idea.
Hit the url twice using the following routes to see it in action.
/test?role
/test?role=Admin (hack to pretend to be an authenticated request)
[System.AttributeUsage(System.AttributeTargets.Property)]
public class SecureProperty : System.Attribute
{
public string Role {get;set;}
public SecureProperty(string role)
{
Role = role;
}
}
[Route("/test")]
public class Test : IReturn
{
public string Name { get; set; }
[SecureProperty("Admin")]
public string SSN { get; set; }
public string SSN2 { get; set; }
public string Role {get;set;}
}
public class TestService : Service
{
public object Get(Test request)
{
// hack to demo roles.
var usersCurrentRole = request.Role;
var props = typeof(Test).GetProperties()
.Where(
prop => ((SecureProperty[])prop
.GetCustomAttributes(typeof(SecureProperty), false))
.Any(att => att.Role != usersCurrentRole)
);
var t = new Test() {
Name = "Joe",
SSN = "123-45-6789",
SSN2 = "123-45-6789" };
foreach(var p in props) {
p.SetValue(t, "xxx-xx-xxxx", null);
}
return t;
}
}
Require().StartHost("http://localhost:8080/",
configurationBuilder: host => { });
I create this demo in ScriptCS. Check it out.
Am practising MVC4 validations and got some basic idea. But am not sure where the Error message comes from in my below code and how to override the message
My model:
[Required(ErrorMessage = "Contact number field is required.")]
public int ContactNumber { get; set; }
when i leave the field empty am getting
Contact number field is required
but when i type any string and submit am getting
The value 'string i typed' is not valid for ContactNumber
how to override my error message ?
Add this validation to your propery which matches for valid number. This way you can override it.
[Required(ErrorMessage = "Contact number field is required.")]
[RegularExpression(#"[0-9]*\.?[0-9]+", ErrorMessage = "Contact number must be a Number.")]
public int ContactNumber { get; set; }
The error message you added was in the "Required" attribute, so it only gets used when something fails the "Required" check, ie. when it is left blank. If you want a particular message for when it's not a number then you'll need to add an attribute to check for that too, and give it a custom error message. A regex should do it. As a nice side effect of this, you can also take the opportunity to do some more detailed checking here, like making sure it's actually in phone number format with the right number of digits and stuff, rather than just checking that the value is numeric.
Im using subsonic 2.2
I tried asking this question another way but didnt get the answer i was looking for.
Basically i ususally include validation at page level or in my code behind for my user controls or aspx pages. However i haev seen some small bits of info advising this can be done within partial classes generated from subsonic.
So my question is, where do i put these, are there particular events i add my validation / business logic into such as inserting, or updating. - If so, and validation isnt met, how do i stop the insert or update. And if anyone has a code example of how this looks it would be great to start me off.
Any info greatly appreciated.
First you should create a partial class for you DAL object you want to use.
In my project I have a folder Generated where the generated classes live in and I have another folder Extended.
Let's say you have a Subsonic generated class Product. Create a new file Product.cs in your Extended (or whatever) folder an create a partial class Product and ensure that the namespace matches the subsonic generated classes namespace.
namespace Your.Namespace.DAL
{
public partial class Product
{
}
}
Now you have the ability to extend the product class. The interesting part ist that subsonic offers some methods to override.
namespace Your.Namespace.DAL
{
public partial class Product
{
public override bool Validate()
{
ValidateColumnSettings();
if (string.IsNullOrEmpty(this.ProductName))
this.Errors.Add("ProductName cannot be empty");
return Errors.Count == 0;
}
// another way
protected override void BeforeValidate()
{
if (string.IsNullOrEmpty(this.ProductName))
throw new Exception("ProductName cannot be empty");
}
protected override void BeforeInsert()
{
this.ProductUUID = Guid.NewGuid().ToString();
}
protected override void BeforeUpdate()
{
this.Total = this.Net + this.Tax;
}
protected override void AfterCommit()
{
DB.Update<ProductSales>()
.Set(ProductSales.ProductName).EqualTo(this.ProductName)
.Where(ProductSales.ProductId).IsEqualTo(this.ProductId)
.Execute();
}
}
}
In response to Dan's question:
First, have a look here: http://github.com/subsonic/SubSonic-2.0/blob/master/SubSonic/ActiveRecord/ActiveRecord.cs
In this file lives the whole logic I showed in my other post.
Validate: Is called during Save(), if Validate() returns false an exception is thrown.
Get's only called if the Property ValidateWhenSaving (which is a constant so you have to recompile SubSonic to change it) is true (default)
BeforeValidate: Is called during Save() when ValidateWhenSaving is true. Does nothing by default
BeforeInsert: Is called during Save() if the record is new. Does nothing by default.
BeforeUpdate: Is called during Save() if the record is new. Does nothing by default.
AfterCommit: Is called after sucessfully inserting/updating a record. Does nothing by default.
In my Validate() example, I first let the default ValidatColumnSettings() method run, which will add errors like "Maximum String lenght exceeded for column ProductName" if product name is longer than the value defined in the database. Then I add another errorstring if ProductName is empty and return false if the overall error count is bigger than zero.
This will throw an exception during Save() so you can't store the record in the DB.
I would suggest you call Validate() yourself and if it returns false you display the elements of this.Errors at the bottom of the page (the easy way) or (more elegant) you create a Dictionary<string, string> where the key is the columnname and the value is the reason.
private Dictionary<string, string> CustomErrors = new Dictionary<string, string>
protected override bool Validate()
{
this.CustomErrors.Clear();
ValidateColumnSettings();
if (string.IsNullOrEmpty(this.ProductName))
this.CustomErrors.Add(this.Columns.ProductName, "cannot be empty");
if (this.UnitPrice < 0)
this.CustomErrors.Add(this.Columns.UnitPrice, "has to be 0 or bigger");
return this.CustomErrors.Count == 0 && Errors.Count == 0;
}
Then if Validate() returns false you can add the reason directly besides/below the right field in your webpage.
If Validate() returns true you can safely call Save() but keep in mind that Save() could throw other errors during persistance like "Dublicate Key ...";
Thanks for the response, but can you confirm this for me as im alittle confused, if your validating the column (ProductName) value within validate() or the beforevalidate() is string empty or NULL, doesnt this mean that the insert / update has already been actioned, as otherwise it wouldnt know that youve tried to insert or update a null value from the UI / aspx fields within the page to the column??
Also, within asp.net insert or updating events we use e.cancel = true to stop the insert update, if beforevalidate failes does it automatically stop the action to insert or update?
If this is the case, isnt it eaiser to add page level validation to stop the insert or update being fired in the first place.
I guess im alittle confused at the lifecyle for these methods and when they come into play