p:autocomplete with POJO - how to get null value? - primefaces

I have a simple problem. I suggest a list of objects to the user to choose from using p:autocomplete. At the same time the user can create new objects 'on the fly' by typing names that are not in the suggestion. The whole setup is very similar to the vanilla POJO showcase, but I'm posting the code here:
<p:autoComplete id="player" value="#{entry.player}"
completeMethod="{abean.complete}"
var="s1" itemLabel="#{s1.name}" itemValue="#{s1}"
converter="PlayerConverter">
<p:ajax event="itemSelect" listener="#{abean.playerSelected}"/>
</p:autoComplete>
The converter:
#FacesConverter(forClass=Player.class, value = "PlayerConverter")
public class PlayerConverter implements Converter
{
#Override
public Object getAsObject(FacesContext ctx, UIComponent cmp, String value)
{
Player player = null;
if ( !(value==null || value.trim().isEmpty()))
{
// Autocomplete did find a match, the appropriate
// player is returned
try
{
Integer id = Integer.valueOf(value);
player = TeamService.getInstance().getPlayer(id);
}
catch (NumberFormatException e)
{
// Autocomplete found no match, the entered String
// is given. Create an ad-hoc player as response
player = new Player();
player.setName(value);
player.setAdHoc(true);
}
}
return player;
}
#Override
public String getAsString(FacesContext ctx, UIComponent cmp, Object value)
{
String result = null;
if (value instanceof String)
{
result = (String) value;
}
else if (value instanceof Spieler)
{
Integer id = ((Spieler)value).getId();
result = (id == null) ? null : id.toString();
}
return result;
}
}
The problem I am facing seems simple: how do I coerce this construction into allowing the user to simply erase a value? When the user deletes the content of the input field, I would expect to get a call to PlayerConverter with a null or empty value, but that doesn't happen.
How do I get my hands on empty input?

I found a workaround. Use a converter and add a flag to the objects you are displaying in the p:autocomplete. Set the flag to 'false' in the converter's getAsString method. Set it to 'true' in the converter's getAsObject method. The latter is not called when the user emptied the autocomplete field. Therefore the flag remains 'false'. And that you can check in the action method of your command button.
I hope it helps someone.

Related

Actually there was zero interactions with this mock error?

I am trying to write test case but stuck with this error. How to fix this error ?
#Override
public boolean isDuplicateSystemDetail(SystemFormBean systemFormBean){
List<BrmSystem> list = systemDao.isDuplicateSystemDetail(systemFormBean);
if(CollectionUtils.isNotEmpty(list)){
return true;
}else{
return false;
}
}
---------------------------------------------------------------------------
#Test
public void isDuplicateSystemDetail_Should_Return_True(){
List<BrmSystem> list = new ArrayList<BrmSystem>();
BrmSystem brmSystem = new BrmSystem();
SystemFormBean systemFormBean = new SystemFormBean();
brmSystem.setSystemName("Test");
list.add(brmSystem);
when(systemDao.isDuplicateSystemDetail(systemFormBean)).thenReturn(list);
}
Probably SystemFormBean class doesn't override equals(). So when isDuplicateSystemDetail(systemFormBean) invokes, it has another object of this class as a parameter which is not the same as the one you've created manually (by default Object.equals() compares memory adresses which would be false in your case).
Try to override equals() to compare by f.e. actual fields of SystemFormBean or rewrite "when" clause as
systemDao.isDuplicateSystemDetail(Mockito.any(SystemFormBean.class))

Passing UTC DateTime to Web API HttpGet Method results in local time

I'm trying to pass a UTC date as a query string parameter to a Web API method. The URL looks like
/api/order?endDate=2014-04-01T00:00:00Z&zoneId=4
The signature of the method looks like
[HttpGet]
public object Index(int zoneId, DateTime? endDate = null)
The date is coming in as 31/03/2014 8:00:00 PM but I'd like it to come in as 01/04/2014 12:00:00 AM
My JsonFormatter.SerializerSettings looks like this
new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
DateTimeZoneHandling = DateTimeZoneHandling.Utc,
DateFormatHandling = DateFormatHandling.IsoDateFormat
};
EDIT #1:
I've noticed when I POST 2014-04-01T00:00:00Z it will serialize to the UTC DateTime kind in C#. However I've found a work around of doing endDate.Value.ToUniversalTime() to convert it although I find it odd how it works for a POST but not a GET.
The query string parameter value you are sending 2014-04-01T00:00:00Z is UTC time. So, the same gets translated to a time based on your local clock and if you call ToUniversalTime(), it gets converted back to UTC.
So, what exactly is the question? If the question is why is this happening if sent in as query string but not when posted in request body, the answer to that question is that ASP.NET Web API binds the URI path, query string, etc using model binding and the body using parameter binding. For latter, it uses a media formatter. If you send JSON, the JSON media formatter is used and it is based on JSON.NET.
Since you have specified DateTimeZoneHandling.Utc, it uses that setting and you get the date time kind you want. BTW, if you change this setting to DateTimeZoneHandling.Local, then you will see the same behavior as model binding.
If you want the conversion to be transparent, then you could use a custom TypeConverter:
public sealed class UtcDateTimeConverter : DateTimeConverter
{
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
return ((DateTime)base.ConvertFrom(context, culture, value)).ToUniversalTime();
}
}
and wire it up using:
TypeDescriptor.AddAttributes(typeof(DateTime), new TypeConverterAttribute(typeof(UtcDateTimeConverter)));
Then the query string parameter will be instantiated as DateTimeKind.Utc.
I ended up just using the ToUniversalTime() method as parameters come in.
So, for those of you who do not wish to override string-to-date conversion in your entire application, and also don't want to have to remember to modify every method that takes a date parameter, here's how you do it for a Web API project.
Ultimately, the general instructions come from here:
https://learn.microsoft.com/en-us/aspnet/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api#model-binders
Here's the specialized instructions for this case:
In your "WebApiConfig" class, add the following:
var provider = new SimpleModelBinderProvider(typeof(DateTime),new UtcDateTimeModelBinder());
config.Services.Insert(typeof(ModelBinderProvider), 0, provider);
Create a new class called UtcDateTimeModelBinder:
public class UtcDateTimeModelBinder : IModelBinder
{
public bool BindModel(HttpActionContext actionContext,
ModelBindingContext bindingContext)
{
if (bindingContext.ModelType != typeof(DateTime)) return false;
var val = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
if (val == null)
{
return false;
}
var key = val.RawValue as string;
if (key == null)
{
bindingContext.ModelState.AddModelError(bindingContext.ModelName,
"Wrong value type");
return false;
}
DateTime result;
if (DateTime.TryParse(key, out result))
{
bindingContext.Model = result.ToUniversalTime();
return true;
}
bindingContext.ModelState.AddModelError(bindingContext.ModelName,
"Cannot convert value to Utc DateTime");
return false;
}
}
I finally find this code , it's not the main answer but it can be used in some cases :
var dateUtc = TimeZoneInfo.ConvertTimeToUtc(date);
DateTimeOffset
Our versioned API classes are automapped to internal classes. Using DateTimeOffset in the URL parameter model of the API and adding a mapping DateTimeOffset => DateTime is effective at preventing the timezone conversion. I.E.
API Class:
public DateTimeOffset? SomeDateTime{ get; set; }
Internal Class:
public DateTime? SomeDateTime{ get; set; }
Mapping profile:
CreateMap<DateTimeOffset, DateTime>();
[This answer expands on the answer from #SeanFausett]
I wanted to have an ISO 8601 date that could have a "Z" on the and the web api function would receive it as a Utc Kind DateTime. But if there was not a "Z", I did not want the conversion.
I also needed to convert dates from incoming POST JSON payloads. The function below can support converting a string to a DateTime, DateTime?, DateTimeOffset, or DateTimeOffset?
It's handy to have dates parse the same way whether form a JSON post or URL parameter. Feel free to tailor the conversion to suit your needs.
//Register the two converters
var jSettings = new Newtonsoft.Json.JsonSerializerSettings()
jSettings.Converters.Add(new UtcDateTimeConverterJSON());
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings = jSettings;
GlobalConfiguration.Configure(config =>
{
TypeDescriptor.AddAttributes(typeof(DateTime), new TypeConverterAttribute(typeof(UtcDateTimeConverterURI)));
WebApiConfig.Register(config);
}
//Date converter for URI parameters
public class UtcDateTimeConverterURI : DateTimeConverter
{
public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
{
if (value?.GetType() == typeof(string))
{
return StringToDate(typeof(DateTime), (string)value, Path: "URI parameter");
}
else
{
return base.ConvertFrom(context, culture, value);
}
}
/// <summary>
/// Convert String to DateTime, DateTime?, DateTimeOffset, or DateTimeOffset?<br />
/// Used for incoming JSON objects and URI parameters
/// </summary>
/// <param name="targetType">The type (i.e. typeof(DateTime))</param>
/// <param name="sDate">string representation of date to be converted</param>
/// <param name="Path">JSON Path in case of error, so the caller knows which parameter to fix</param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public static object StringToDate(Type targetType, string sDate, string Path)
{
//if the object is a DateTime, determine if we need to return a UTC or Local date type
bool returnUTC = false;
//DateTime or DateTimeOffset return type
bool isDateTimeOffset;
if (targetType == typeof(DateTime?) || targetType == typeof(DateTime))
{
isDateTimeOffset = false;
}
else
{
isDateTimeOffset = true;
}
DateTimeOffset d;
if (String.IsNullOrEmpty(sDate))
{
//if we have an empty string and the type is a nullable date, then return null... otherwise throw an error
if (targetType == typeof(DateTime?))
{
return null;
}
else
{
throw new Exception(Path + " cannot be an empty Date");
}
}
if (sDate[0] == '/')
{
// /Date(xxxxx)/ format
sDate = sDate.Substring(6, sDate.Length - 8);
var index = sDate.LastIndexOf('-');
if (index == -1) index = sDate.LastIndexOf('+');
if (index >= 0)
{
//lop off timezone offset
sDate = sDate.Substring(0, index);
}
else
{
//no timezone offset, return as UTC
returnUTC = true;
}
if (!Int64.TryParse(sDate, out var l))
{
//can't parse....
throw new Exception(Path + " cannot be parsed as a Date");
}
else
{
d = DateTimeOffset.FromUnixTimeMilliseconds(l);
}
}
else
{
//try and parse ISO8601 string
if (!DateTimeOffset.TryParse(sDate, out d))
{
throw new Exception(Path + " cannot be parsed as a Date");
}
else
{
if (!isDateTimeOffset)
{
//if UTC is specifically requested and we're not returning a DateTimeOffset, then make sure the return is UTC
if (d.Offset == TimeSpan.Zero && sDate[sDate.Length - 1] == 'Z') returnUTC = true;
}
}
}
if (isDateTimeOffset)
{
return d;
}
else
{
if (returnUTC)
{
return d.UtcDateTime;
}
else
{
//return the raw time passed in, forcing it to the "Local" Kind
//for example:
//"2020-03-27T12:00:00" --> use 2020-03-27 12:00:00PM with Kind=Local
//"2020-03-27T12:00:00-05:00" --> use 2020-03-27 12:00:00PM with Kind=Local
return DateTime.SpecifyKind(d.DateTime, DateTimeKind.Local); //this will pull the raw time and force the Kind to "Local"
}
}
}
}
//Date converter for JSON payloads
public class UtcDateTimeConverterJSON : DateTimeConverterBase
{
public override bool CanRead
{
get
{
return true;
}
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.Value == null || reader.TokenType == JsonToken.Date) return reader.Value;
if (reader.TokenType != JsonToken.String) throw new Exception("Cannot parse Date");
return UtcDateTimeConverterURI.StringToDate(objectType, (string)reader.Value, reader.Path);
}
}

Web API 2 - returning JSON, a property that is false is not included

The JSON returned when a REST request is made all works great except any bool property, if false, does not get included in the JSON (verified via Fiddler). I tried:
[DataMember(IsRequired = true)]
public bool success { get; set; }
but it still didn't return it.
Any suggestions? And I do like that it doesn't return anything for nulls, it's just bools that I want always returned.
WebApiConfig.cs:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
config.Formatters.XmlFormatter.UseXmlSerializer = true;
config.Formatters.JsonFormatter.SerializerSettings.DefaultValueHandling = Newtonsoft.Json.DefaultValueHandling.IgnoreAndPopulate;
config.Formatters.JsonFormatter.SerializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore;
}
}
DatasourceController.cs:
public class DatasourceController : ApiController
{
[HttpGet("datasource/metadata/{datasource}")]
public MetaDataInfo GetDatasourceSchema(string datasource, string node = "")
{
DocumentInfo docInfo = DocumentData.GetDocInfo("dave");
return MetaDataFactory.GetMetaDataInfo(docInfo, datasource, node);
}
}
I was looking for the same information.
It turns out you can specify for a specific property using:
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Include)]
I've tested on ASP.NET Core 1 RC2.
That's MVC 6.
I think that by putting the [DefaultValue(false)] attribute above your success variable and other bool variables you should get your desired result.
You have set DefaultValueHandling to Newtonsoft.Json.DefaultValueHandling.IgnoreAndPopulate. From the documentation we can read:
Ignore members where the member value is the same as the member's default value when serializing objects and sets members to their default value when deserializing.
As I read that it means that during serializing your false boolean values should disappear. However, as long as it has a default value it will appear in the JSON again when you deserialize.

How can I define a boolean function argument to be optional?

In ActionScript 3, is there a clean way to define a function that accepts an optional boolean argument ? As you may know, this is invalid :
public function test(param:Boolean = null):void {
trace(param);
}
This triggers the following error: VerifyError: Error #1102: Illegal default value for type Boolean. Since, Boolean is a primitive, I guess it makes sense that it cannot be set to null. The only workaround I found is to cast the parameter to an object :
public function test(param:Object = null):void {
trace(Boolean(param));
}
However, this does not feel very clean, particularly if you are developing libraries. ASDoc will generate API documentation that says the expected parameter is an Object whereas what is really needed is a Boolean.
Is there a better approach ?
When you say optional, I assume that you mean if there isn't a value supplied then something different should happen compared to if you had a default value of true or false.
You could make your own object to handle the three states that you need and maintain code readability by using a class like this:
public class Condition
{
private var _value:* = null;
public function Condition(initial:* = null)
{
value = initial;
}
public function set value(n:*):void
{
if(_value === null || _value === false || _value === true)
{
_value = n;
}
}
public function get value():*{ return _value; }
}
And then your function could be:
function test(param:Condition = null):void
{
if(param && param.value != null)
{
trace(param.value);
}
}
test( new Condition() );
test( new Condition(true) );
As you said Boolean can not be set to null value.
Therefore, you should specify a default value that is either true or false.
public function test(param:Boolean = false):void {
trace(param);
}
But because you need the third case where nothing is set, one option could be to accept any Object but throw an exception if it is not null and not a boolean:
public function test(param:* = null):void
{
if (param != null)
{
if ((param == true) || (param == false))
{
trace(Boolean(param).toString());
}
else
{
throw new CustomError("param should be a boolean");
}
}
else
{
// Do nothing
}
}
Note that this solution also accept objects or primitives that can be compared to true or false such as 0, 1, or [].
From the good suggestions and discussion above I think that, in a library scenario and for simplicity's sake, the best way remains to type the parameter as Object with a default value of null but to request a Boolean in the API documentation :
/**
* #param param Boolean object or null
*/
public function test(param:Object = null):void {
trace(Boolean(param));
}
This allow the user of the library to pass a either a Boolean or nothing at all. Thanks everyone.
There was a tonne of discussion on my previous answer, but this is the correct way to have a function that accepts one of three states. My previous answer attempted to retain the use of a Boolean value like you were requesting, but that is not the right way to go about it.
Create a class that defines three values:
class State
{
public static const EMPTY:int = -1;
public static const FALSE:int = 0;
public static const TRUE:int = 1;
}
Your function will accept an int (the type of each of the three properties within your State class). It will deal with the three possible values. You can use concise commenting to notify the developer of what thee values the function is expecting, referencing the State class. The default value can be -1 aka State.EMPTY.
/**
* Function description.
* #param state One of three states, defined by State.
*/
function test(state:int = -1):void
{
switch(state)
{
case State.EMPTY:
// No value given.
break;
case State.TRUE:
// True.
//
break;
case State.FALSE:
// False.
//
break;
default:
throw new ArgumentError("Unsupported value for test()");
break;
}
}

Find out what fields are being updated

I'm using LINQ To SQL to update a user address.
I'm trying to track what fields were updated.
The GetChangeSet() method just tells me I'm updating an entity, but doesn't tell me what fields.
What else do I need?
var item = context.Dc.Ecs_TblUserAddresses.Single(a => a.ID == updatedAddress.AddressId);
//ChangeSet tracking
item.Address1 = updatedAddress.AddressLine1;
item.Address2 = updatedAddress.AddressLine2;
item.Address3 = updatedAddress.AddressLine3;
item.City = updatedAddress.City;
item.StateID = updatedAddress.StateId;
item.Zip = updatedAddress.Zip;
item.Zip4 = updatedAddress.Zip4;
item.LastChangeUserID = request.UserMakingRequest;
item.LastChangeDateTime = DateTime.UtcNow;
ChangeSet set = context.Dc.GetChangeSet();
foreach (var update in set.Updates)
{
if (update is EberlDataContext.EberlsDC.Entities.Ecs_TblUserAddress)
{
}
}
Use ITable.GetModifiedMembers. It returns an array of ModifiedMemberInfo objects, one for each modified property on the entity. ModifiedMemberInfo contains a CurrentValue and OriginalValue, showing you exactly what has changed. It's a very handy LINQ to SQL feature.
Example:
ModifiedMemberInfo[] modifiedMembers = context.YourTable.GetModifiedMembers(yourEntityObject);
foreach (ModifiedMemberInfo mmi in modifiedMembers)
{
Console.WriteLine(string.Format("{0} --> {1}", mmi.OriginalValue, mmi.CurrentValue));
}
You can detect Updates by observing notifications of changes. Notifications are provided through the PropertyChanging or PropertyChanged events in property setters.
E.g. you can extend your generated Ecs_TblUserAddresses class like this:
public partial class Ecs_TblUserAddresses
{
partial void OnCreated()
{
this.PropertyChanged += new PropertyChangedEventHandler(User_PropertyChanged);
}
protected void User_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
string propertyName = e.PropertyName;
// do what you want
}
}
Alternatively, if you want to track a special property changing, you could use one of those OnPropertyNameChanging partial methods, e.g. (for City in your example):
partial void OnCityChanging(string value)
{
// value parameter holds a new value
}