JPA 2.1 Type Converter doesn't get executed on NULL values - entitymanager

I'm testing the new JPA 2.1 Type Converters. I want to avoid NULL String values to be stored in a legacy database as they are not allowed. So I defined the following converter:
#Converter(autoApply=true)
public class CString implements AttributeConverter<String, String> {
#Override
public String convertToDatabaseColumn(String str) {
if( str == null || str.length() == 0 ) {
return " ";
} else {
return str;
}
}
#Override
public String convertToEntityAttribute(String str) {
if( str == null || str.length() == 0 || str.equals(" ") ) {
return null;
} else {
return str;
}
}
}
String properties should be converted to a space character if they are NULL, but the converter method's are not executed when the properties are NULL.
I'm trying hibernate-jpa-2.1-api (1.0.0.Final) and hibernate-entitymanager (4.3.6.Final).
Is there any JPA 2.1 compliant way to get around this?

UPDATE: this bug has been resolved in the latest Hibernate 5.0.0.Beta1 as part of JIRA issue HHH-8697 and will be in Hibernate 4.3.9 as soon as it is released from the 4.3.9-SNAPSHOT version
If you don't want to upgrade to the beta version, you can use a workaround: take a look at JPA/Hibernate map null which explains using the getter and setter to implement your logic.

Related

#Mapping on mapstruct with List<> Of List<>

I've recently started to use mapstruct, while coding I stuck with a scenario. In order to solve the ambiguity between the below default methods, I'm trying to use the "qualifiedBy" on a List<
#Mapping(qualifiedBy = LineTestBO). Line => 1
List<ReturnABO> toCaptureLineItemsBOs(List<LineDTO> lineDTO);
#Named("LineTestBO")
default ReturnABO map(LineDTO lineDTO) {
if (lineDTO.getCurrency() != null && lineDTO.getNationalPermit() != null &&
lineDTO.getAmount() != null && lineDTO != null)
return this.toBO(lineDTO);
return null;
}
default returnABO toBO(LineDTO lineDTO) {
// To do here
}
But Line 1 shows the error as it needs to "target" to be specified. I'm not sure what should be the target here since Line is a collection object. Even If I don't use the #mapping the mapstuct generates the mapper implementation. I read the mapstuct documentation but could not follow much for this scenario. How the Named annotation can be used on List to explicity denote that this is name to be used ? Can someone help me? Thanks.
the target must be specified, so if your POJOs look like this
class A {
private List<ReturnABO> x;
}
class B {
private List<LineDTO> x;
}
in your mapper, you could have something like this
interface AMapper {
#Mapping(target="x", source="x", qualifiedByName = "LineTestBO")
A toA(B b);
#Named("LineTestBO")
default List<ReturnABO> lineTestBO (List<LineDTO> lines) {
return lines.stream().map(this::map).collect(Collectors.toList())
}
default ReturnABO map(LineDTO lineDTO) {
if (lineDTO.getCurrency() != null && lineDTO.getNationalPermit() != null &&
lineDTO.getAmount() != null && lineDTO != null)
return this.toBO(lineDTO);
return null;
}
}
The reason for the error is that using #Mapping on iterable mapping method doesn't make much sense.
What you are looking for is IterableMapping#qualifiedBy.
So in your case the mapper needs to look like:
#Mapper
public interface MyMapper {
#IterableMapping(qualifiedByName = "LineTestBO")
List<ReturnABO> toCaptureLineItemsBOs(List<LineDTO> lineDTO);
#Named("LineTestBO")
default ReturnABO map(LineDTO lineDTO) {
if (lineDTO.getCurrency() != null && lineDTO.getNationalPermit() != null && lineDTO.getAmount() != null && lineDTO != null) {
return this.toBO(lineDTO);
}
return null;
}
default returnABO toBO(LineDTO lineDTO) {
// To do here
}
}

how to use "not equal to" in where condition using linq with entity framework

how to use "not equal to" in where condition using LINQ with entity framework.
public ActionResult ViewOfficeType()
{
return View(entity.TBL_OFFICETYPE.Where(p => p.STATUS<>"D").ToList());
}
it shows invalid expression '>'
if i use '!='.It doesn't show error.But it doesn't work.
you can use the ! operator on Equals()
public ActionResult ViewOfficeType()
{
return View(entity.TBL_OFFICETYPE.Where(p => !p.Equals("D")).ToList());
}
You can you use the following approaches
Use != operator in you lambda expression
public ActionResult ViewOfficeType()
{
return View(entity.TBL_OFFICETYPE.Where(p => p.STATUS != "D").ToList());
}
Use !string.Equals
public ActionResult ViewOfficeType()
{
return View(entity.TBL_OFFICETYPE.Where(p => !p.STATUS.Equals("D")).ToList());
}
Note: Be aware of string comparison issues like character encoding, and case sensitivity etc.
I would prefer a Extension method as follows:
public static class StringExtension
{
public static bool NotEquals(this string source, string target)
{
return !(source.Equals(target));
}
}
How it works:
string source = "Test"; // Sample / Source data
// Tested with "test", result is true, since the case is different, so two strings are different
source.NotEquals("test");
// Tested with "Test", result is false, since they are same
source.NotEquals("Test");
Lot more things are possible inside the extension method, based on whether you want to ignore the case, you can simply pass StringComparison.OrdinalIgnoreCase in the Equals method, then "Test" will be evaluated equal to "test" (case ignored)
var status = entity.TBL_OFFICETYPE.Select(p => p.STATUS == "D");
return View(entity.TBL_OFFICETYPE.Where(p => !status.Contains(p.STATUS == "D")).ToList());
plz try this

grails 3 overriding queryForResource not working

According to Grails Web Services
I can override the method queryForResource. This way I may be able to specify nested REST resource. e.g
"/authors"(resources:'author') {
"/books"(resources:'book')
}
But the doc may be wrong. Because it uses an assigment operator = instead a comparison one ==.
Running This way I get the following error:
((id == id) && building.id) is a binary expression, but it should be a variable expression
Changing the operator from = to == I get another error
Cannot query property "params" - no such property on class clash.BuildingLevel exists
What is the correct way to define this nested REST resource?
Here is my queryForResource method:
I tried both:
#Override
protected BuildingLevel queryForResource(Serializable id) {
if (params.buildingId) {
return BuildingLevel.where {
id == id && building.id = params.buildingId
}.find()
}
}
#Override
protected BuildingLevel queryForResource(Serializable id) {
if (params.buildingId) {
return BuildingLevel.where {
id == id && building.id == params.buildingId
}.find()
}
}
I just figure it out.
The following post issues-posting-nested-resource-in-grails helped me.
The params cannot be inside the where clause. So It's necessary to create a local variable to keep the value. Like this:
#Override
protected BuildingLevel queryForResource(Serializable id) {
def myLocalVariablebuildingId = params.buildingId
if (params.buildingId) {
return BuildingLevel.where {
id == id && building.id == myLocalVariablebuildingId
}.find()
}
}

How to remove default value('0') in WicketTextField

Here iam using a wicketText Textfield component to which an Integer type is mapped, Now on load of page iam getting the '0' as default value in that textfield. How to remove that 0 from the textfield.
Don't use int as the property type: that can't be null. Use Integer instead.
The TextField converts the value of the object in the model to a String. In case the object is null, the String will be empty.
You are probably using a int as Matrijn indicated. The java built-in primitive type can never be null but defaults to 0
So use a Integer. (Or you could create a custom Converter, but that is just messy)
what about using NumberTextField like this
NumberTextField numberField = (NumberTextField) new NumberTextField("numberField",
new Model(10));
I believe You may be using int instead of Integer. (int cannot be null, while Integer can)
Try to customize the Converter of your TextField
public class Converter<C> implements IConverter<C> {
#Override
public C convertToObject(String s, Locale locale) throws ConversionException {
return (C) s;
}
#Override
public String convertToString(C c, Locale locale) {
Class<? extends Object> aclass = c.getClass();
if (aclass == Long.class) {
return ((Long) c != 0) ? String.valueOf(c) : "";
} else if (aclass == Integer.class) {
return ((Integer) c != 0) ? String.valueOf(c) : "";
} else if (aclass == BigDecimal.class) {
return (!BigDecimal.ZERO.equals(c)) ? String.valueOf(c) : "";
}
return c.toString();
}
}
and then, override the default IConverter
new TextField<BigDecimal>("id") {
#Override
public <C> IConverter<C> getConverter(Class<C> type) {
return new Converter<C>();
}
}
The generic type of text field should be a reference. The Integer is good choice. But for a good programming choice it is better to use String.The new Model("") make your text field empty.
TextField<Integer> a = new TextField<Integer>("id",new Model(""));
you can get the integer value of your textfield by a.getValue() method.You can parse the such strings to int by Integer.parseInt(a.getValue()); property.
TextField<String> a = new TextField<String>("id",new Model(""));

jQuery.validate error in IE

I have an MVC application which I have added custom cross-field validation. The cross-field validation isn't configured to be client-side however when I tab through my fields IE is throwing the following error "$.validator.method[...] is null or not an object" from within jquery.validate.js. I have attached the full version so I can debug what's going on and it seems to be trying to fire my "mandatoryif" custom validation below on the client-side and then throwing the error at the following line:
var result = $.validator.methods[method].call( this, element.value.replace(/\r/g, ""), element, rule.parameters );
Any ideas why it is trying to do this when the "mandatoryif" validation hasn't been added client-side?
I have also updated to the latest version as I read it could be the version of jQuery.validate but this didn't fix the issue either.
Here is my custom validation:
Attribute
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
public class MandatoryIfAttribute : ValidationAttribute, ICrossFieldValidationAttribute
{
public string OtherProperty { get; set; }
public bool IsValid(ControllerContext controllerContext, object model, ModelMetadata modelMetadata)
{
if (model == null)
{
throw new ArgumentNullException("model");
}
// Find the value of the other property.
var propertyInfo = model.GetType().GetProperty(OtherProperty);
if (propertyInfo == null)
{
throw new InvalidOperationException(string.Format("Couldn't find {0} property on {1}.",
OtherProperty, model));
}
var otherValue = propertyInfo.GetGetMethod().Invoke(model, null);
if (modelMetadata.Model == null)
{
modelMetadata.Model = string.Empty;
}
if (otherValue == null)
{
otherValue = string.Empty;
}
return (String.IsNullOrEmpty(modelMetadata.Model.ToString()) && (String.IsNullOrEmpty(otherValue.ToString()) || otherValue.ToString() == "0")) || (!String.IsNullOrEmpty(modelMetadata.Model.ToString()) && String.IsNullOrEmpty(otherValue.ToString())) || (!String.IsNullOrEmpty(modelMetadata.Model.ToString()) && !String.IsNullOrEmpty(otherValue.ToString()));
}
public override bool IsValid(object value)
{
// Work done in other IsValid
return true;
}
Validator
public class MandatoryIfValidator : CrossFieldValidator<MandatoryIfAttribute>
{
public MandatoryIfValidator(ModelMetadata metadata, ControllerContext controllerContext,
MandatoryIfAttribute attribute) :
base(metadata, controllerContext, attribute)
{
}
public override IEnumerable<ModelClientValidationRule> GetClientValidationRules()
{
var rule = new ModelClientValidationRule
{
ValidationType = "mandatoryif",
ErrorMessage = Attribute.FormatErrorMessage(Metadata.PropertyName),
};
rule.ValidationParameters.Add("otherProperty", Attribute.OtherProperty);
return new[] { rule };
}
Appreciate any help on this.
I have managed to find the answer to my query. Because some of my custom validation was doing lookups to the db I didn't want the overhead of this being done client-side so there was no client-side code. However, I didn't realise that by adding
DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(MandatoryIfAttribute),
typeof(MandatoryIfValidator));
in Global.asax that it was in affect adding this client-side. Of course because there was no code to process client-side it was throwing the validaiton error.