Expression Language Other way to invoke method - jsf-2

I have the following code and I'm searching for an other way to do this.
public static RequestContextData getRequestContextData() {
FacesContext fc = FacesContext.getCurrentInstance();
ExpressionFactory ef = fc.getApplication().getExpressionFactory();
MethodExpression me = ef.createMethodExpression( fc.getELContext(), "#{requestContextData.getRequestContextData}", String.class, new Class[0]);
Object o = me.invoke(fc.getELContext(), null);
RequestContextData request = (RequestContextData) o;
return request;
}
I found out that it causes problems after upgrading to tomcat 8. The ELContext is already resolved and with this code afterwards it wouldn't be resolved anymore. I already tried it with a managed property but this won't work.
Addition 1:
The stack looks like the following:
xxx.getRequestContextData()
some other methods
BeanELResolver.getValue(ELContext, Object, Object)
The ELContext is in BeanELResolver and xxx the same one. That leads to the malfunction that the xxx overwrites the resolved property with false in the BeanELResolver which then returns an PropertyNotFoundException.

Related

How to call Managed bean method in using expression language

I am developing a utility class, using this we need to call a managed bean method which is defined in EL Expression. Is there any examples like how to invoke a managed bean method using EL expression.
Here I don't know the type of Managed bean. but I know EL expression. So I cannot type cast to specific managed bean.
The expression is: #{phaseListenerBean.compListener}
How can my code call the compListener method on phaseListenerBean?
My Utility class. It is avaliable in a Jar file.
`public void beforePhase(PhaseEvent event) {
if(PhaseId.RENDER_RESPONSE.equals(event.getPhaseId())){
SystemListLoaderHelper.populateSelectOneValidValues();
SystemListLoaderHelper.populateSelectManyCheckboxValidValues();
FacesContext context = FacesContext.getCurrentInstance();
ExpressionFactory factory =context.getApplication().getExpressionFactory();
MethodExpression methodExpression = factory.createMethodExpression(
context.getELContext(), "#{phaseListenerBean.callModuleSpecificServiceCalls}",
Void.class.getClass(), null);
methodExpression.invoke(context.getELContext(), null);
// callModuleSpecificServiceCalls();
}
}`
You can try call the bean with the Faces context, for example if you want the bean, you can use:
FacesContext facesContext = FacesContext.getCurrentInstance();
Object o = facesContext.getApplication().evaluateExpressionGet(facesContext,
"#{phaseListenerBean}", Object.class);
And later use reflection to call the method or, You can call the method whith your expression, like this:
FacesContext fc = getContext();
ExpressionFactory factory = getExpressionFactory();
methodExpression = factory.createMethodExpression(
fc.getELContext(), "#{phaseListenerBean.compListener}",
Void.class, (Class<?>) null);
methodExpression.invoke(fc.getELContext(), null);
Please show some code for "compListener" and the utility class. Sorry for my bad english,
Cheers

NewtonSoft json Contract Resolver with MVC 4.0 Web Api not producing the output as expected

I am trying to create a conditional ContractResolver so that I can control the serialization differently depending on the web request/controller action.
For example in my User Controller I want to serialize all properties of my User but some of the related objects I might only serialize the primitive types. But if I went to my company controller I want to serialize all the properties of the company but maybe only the primitive ones of the user (because of this I don't want to use dataannotations or shouldserialize functions.
So looking at the custom ContractResolver page i created my own.
http://james.newtonking.com/projects/json/help/index.html?topic=html/ContractResolver.htm
It looks like this
public class IgnoreListContractResolver : DefaultContractResolver
{
private readonly Dictionary<string, List<string>> IgnoreList;
public IgnoreListContractResolver(Dictionary<string, List<string>> i)
{
IgnoreList = i;
}
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
List<JsonProperty> properties = base.CreateProperties(type, memberSerialization).ToList();
if(IgnoreList.ContainsKey(type.Name))
{
properties.RemoveAll(x => IgnoreList[type.Name].Contains(x.PropertyName));
}
return properties;
}
}
And then in my web api controller action for GetUsers i do this
public dynamic GetUsers()
{
List<User> Users = db.Users.ToList();
List<string> RoleList = new List<string>();
RoleList.Add("UsersInRole");
List<string> CompanyList = new List<string>();
CompanyList.Add("CompanyAccesses");
CompanyList.Add("ArchivedMemberships");
CompanyList.Add("AddCodes");
Dictionary<string, List<string>> IgnoreList = new Dictionary<string, List<string>>();
IgnoreList.Add("Role", RoleList);
IgnoreList.Add("Company", CompanyList);
GlobalConfiguration
.Configuration
.Formatters.JsonFormatter
.SerializerSettings
.ContractResolver = new IgnoreListContractResolver(IgnoreList);
return new { List = Users, Status = "Success" };
}
So when debugging this I see my contract resolver run and it returns the correct properties but the Json returned to the browser still contains entries for the properties I removed from the list.
Any ideas what I am missing or how I can step into the Json serialization step in webapi controllers.
*UPDATE**
I should add that this is in an MVC4 project that has both MVC controllers and webapi controllers. The User, Company, and Role objects are objects (created by code first) that get loaded from EF5. The controller in question is a web api controller. Not sure why this matters but I tried this in a clean WebApi project (and without EF5) instead of an MVC project and it worked as expected. Does that help identify where the problem might be?
Thanks
*UPDATE 2**
In the same MVC4 project I created an extension method for the Object class which is called ToJson. It uses Newtonsoft.Json.JsonSerializer to serialize my entities. Its this simple.
public static string ToJson(this object o, Dictionary<string, List<string>> IgnoreList)
{
JsonSerializer js = JsonSerializer.Create(new Newtonsoft.Json.JsonSerializerSettings()
{
Formatting = Formatting.Indented,
DateTimeZoneHandling = DateTimeZoneHandling.Utc,
ContractResolver = new IgnoreListContractResolver(IgnoreList),
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
});
js.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter());
var jw = new StringWriter();
js.Serialize(jw, o);
return jw.ToString();
}
And then in an MVC action i create a json string like this.
model.jsonUserList = db.Users.ToList().ToJson(IgnoreList);
Where the ignore list is created exactly like my previous post. Again I see the contract resolver run and correctly limit the properties list but the output json string still contains everything (including the properties I removed from the list). Does this help? I must be doing something wrong and now it seems like it isn't the MVC or web api framework. Could this have anything to do with EF interactions/ proxies /etc. Any ideas would be much appreciated.
Thanks
*UPDATE 3***
Process of elimination and a little more thorough debugging made me realize that EF 5 dynamic proxies were messing up my serialization and ContractResolver check for the type name match. So here is my updated IgnoreListContractResolver. At this point I am just looking for opinions on better ways or if I am doing something terrible. I know this is jumping through a lot of hoops just to use my EF objects directly instead of DTOs but in the end I am finding this solution is really flexible.
public class IgnoreListContractResolver : CamelCasePropertyNamesContractResolver
{
private readonly Dictionary<string, List<string>> IgnoreList;
public IgnoreListContractResolver(Dictionary<string, List<string>> i)
{
IgnoreList = i;
}
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
List<JsonProperty> properties = base.CreateProperties(type, memberSerialization).ToList();
string typename = type.Name;
if(type.FullName.Contains("System.Data.Entity.DynamicProxies.")) {
typename = type.FullName.Replace("System.Data.Entity.DynamicProxies.", "");
typename = typename.Remove(typename.IndexOf('_'));
}
if (IgnoreList.ContainsKey(typename))
{
//remove anything in the ignore list and ignore case because we are using camel case for json
properties.RemoveAll(x => IgnoreList[typename].Contains(x.PropertyName, StringComparer.CurrentCultureIgnoreCase));
}
return properties;
}
}
I think it might help if you used Type instead of string for the ignore list's key type. So you can avoid naming issues (multiple types with the same name in different namespaces) and you can make use of inheritance. I'm not familiar with EF5 and the proxies, but I guess that the proxy classes derive from your entity classes. So you can check Type.IsAssignableFrom() instead of just checking whether typename is a key in the ignore list.
private readonly Dictionary<Type, List<string>> IgnoreList;
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
List<JsonProperty> properties = base.CreateProperties(type, memberSerialization).ToList();
// look for the first dictionary entry whose key is a superclass of "type"
Type key = IgnoreList.Keys.FirstOrDefault(k => k.IsAssignableFrom(type));
if (key != null)
{
//remove anything in the ignore list and ignore case because we are using camel case for json
properties.RemoveAll(x => IgnoreList[key].Contains(x.PropertyName, StringComparer.CurrentCultureIgnoreCase));
}
return properties;
}
Then the ignore list must be created like this (I also used the short syntax for creating the list and dictionary):
var CompanyList = new List<string> {
"CompanyAccesses",
"ArchivedMemberships",
"AddCodes"
};
var IgnoreList = new Dictionary<Type, List<string>> {
// I just replaced "Company" with typeof(Company) here:
{ typeof(Company), CompanyList }
};
Be aware that, if you use my code above, adding typeof(object) as the first key to the ignore list will cause this entry to be matched every time, and none of your other entries will ever be used! This happens because a variable of type object is assignable from every other type.

How to hook up SqlDataAdapter to profile db operations with mvc mini profiler

I looked up How could I instantiate a Profiled DataAdapter to use with MVC MINI PROFILER? but this also did not answer my question.
I have some code like this in SqlDatasource class -
protected SqlCommand sqlCommand;
public SqlDatasource(String query, String connectionString) : this(connectionString)
{
this.sqlCommand.CommandText = query;
}
public DataTable getResults()
{
DataTable table = new DataTable();
SqlDataAdapter adapter = new SqlDataAdapter(this.sqlCommand);
SqlCommandBuilder commandBuilder = new SqlCommandBuilder(adapter);
adapter.Fill(table);
return table;
}
I want a way to hook into the SqlDataAdapter when getResults() gets called. I searched a lot but there did not seem a way for me to do this yet.
Thanks.
There's a class ProfiledDbDataAdapter provided for this that you can use wrapped around your existing SqlDataAdapter.
When I tried using it I found I needed to use the Fill(DataSet) method instead of Fill(DataTable) else I always received an error "The SelectCommand property has not been initialized before calling 'Fill'." despite setting both adapter's SelectCommand properties.

Enterprise Library 5.0, CreateSprocAccessor and Timeout

Is there a way to set the timeout for CreateSprocAccessor(...) in Enterprise Library 5.0?
Cause the default timeout is not working for long stored procedures.
First thing: adding a timeout in the connection string doesn't solve the problem.
I found a workaround: You can modify the source code of EL 5.0 and generate a new custom DLL.
in ...\EntLib50Src\Blocks\Data\Src\Data\SprocAccessor.cs
in Execute(...) method
add this code just before return: command.CommandTimeout = 120; // 2 mins
Compile and use the new Microsoft.Practices.EnterpriseLibrary.Data.dll that you can find in ...\EntLib50Src\Blocks\bin\Debug
actually, I think there is no need to have your own copy of EL. In order to keep original EL binaries unchanged, you just can do the follow:
inherit from SprocAccessor class
overwrite Execute() method, put here the same code as in SprocAccessor.Execute() but adding the timeout part
you will need also to keep in local variable (in your new class) procedureName as this variable is private in SprocAccessor class
some thing like this:
public class SprocAccessorWithTimeout<T> : SprocAccessor<T>
{
readonly string procedureName;
public SprocAccessorWithTimeout(Database database, string procedureName, IRowMapper<T> rowMapper) : base(database, procedureName, rowMapper)
{
this.procedureName = procedureName;
}
public override IEnumerable<T> Execute(params object[] parameterValues)
{
using (var command = Database.GetStoredProcCommand(this. procedureName))
{
command.CommandTimeout = MaxSpExecutionTimeout;
if (parameterValues.Length > 0)
{
Database.AssignParameters(command, parameterValues);
}
return base.Execute(command);
}
}
}

Error: “An entity object cannot be referenced by multiple instances of IEntityChangeTracker"

I'm currently using the repository pattern in an ASP.Net MVC project and have the following code:
partial class Timesheet : ITimesheet
{
TimeSystemDBEntities _db;
public Timesheet()
{
_db = new TimeSystemDBEntities();
}
.
.
//More Methods
.
.
//Save WorkWeek to database
private void SaveWorkWeek(WorkWeek wk)
{
//Creating a new test context in attempt to resolve
//Error: “An entity object cannot be referenced by multiple instances of IEntityChangeTracker"
var testContext = new TimeSystemDBEntities();
var newWorkWeek = new WorkWeek();
var newStudent = new Student();
//Copy contents of wk to newWorkWeek
newWorkWeek.Students = newStudent.GetStudent(wk.Students.id);
newWorkWeek.MonDate = wk.MonDate;
newWorkWeek.MonHours = wk.MonHours;
newWorkWeek.TuesDate = wk.TuesDate;
newWorkWeek.TuesHours = wk.TuesHours;
newWorkWeek.WedDate = wk.WedDate;
newWorkWeek.WedHours = wk.WedHours;
newWorkWeek.ThursDate = wk.ThursDate;
newWorkWeek.ThursHours = wk.ThursHours;
newWorkWeek.FriDate = wk.FriDate;
newWorkWeek.FriHours = wk.FriHours;
newWorkWeek.TempSave = wk.TempSave;
testContext.AddToWorkWeek(newWorkWeek); //Exception thrown here
testContext.SaveChanges();
//Also tried
//_db.AddToWorkWeek(newWorkWeek); //Exception thrown here
//_db.SaveChanges();
//Also tried
//_db.detach(wk): //Different exception thrown here: Says it's not in ObjectStateManager
//_db.AddToWorkWeek(newWorkWeek);
//_db.SaveChanges();
//Also tried
//_db.detach(wk.Students): //Different exception thrown here: Says it's not in ObjectStateManager
//_db.AddToWorkWeek(newWorkWeek);
//_db.SaveChanges();
}
}
The Student and WorkWeek classes are in a 1-to-Many relationship, respectively. I have tried everything from detaching to creating a completely new context as in the example code above and cannot get the object to save. When I try and detach it basically says it's not in the ObjectStateManager, which I interpret as there's nothing to detach, which ,if true, seems to contradict the original error. I'm not sure what's going on, any help is appreciated.
#Craig, thanks I had actually already looked at those links and their solutions and attempted to implement them with no success.
The following link provided me with the solution to my problem, also has other very useful information about other miscellaneous issues that have to do with the Entity Framework.
Entity Framework Gotchas
I am new to MVC & Entity frame work. I got same problem after fighting a lot
This solution worked for me. Hope it can be useful for you guys.
var mediaItem = db.MediaItems.FirstOrDefault(x => x.Id == mediaItemViewModel.Id);
mediaItem.Name = mediaItemViewModel.Name;
mediaItem.Description = mediaItemViewModel.Description;
mediaItem.ModifiedDate = DateTime.Now;
mediaItem.FileName = mediaItem.FileName;
mediaItem.Size = KBToMBConversion(mediaItemViewModel.Size);
mediaItem.Type = mediaItem.Type;
//db.Entry(mediaItem).State = EntityState.Modified;// coment This line
db.SaveChanges();
Cause you are reading the the whole object from db and holding it in the current context and when you try to modify the entity state its tells you already one entity attached to the current context. just call save changes it will save it.

Resources