I create a method on the session facade, that returns a custom entity collection.
I publish it in the local interface.
I bind corresponding data control iterator to an ADF table.
When run, it shows "No data to display".
There are no exceptions in the weblogic console.
public List<Users> getCollection() {
List<Users> l = new ArrayList<Users>();
Users u = em.find(Users.class, new BigDecimal(999));
System.out.println(u.getName());
l.add(u);
return l;
}
When I invoke this method via another method, bound to a ADF button,
all is fine though.
User name is printed to the weblogic console.
public int printCollectionSize() {
return getCollection().size();
}
When I bind to an ADF table a data control iterator created from (autogenerated) method getUsersFindAll, all is fine too.
public List<Users> getUsersFindAll() {
return em.createNamedQuery("Users.findAll").getResultList();
}
I am completely lost. Is my method never gets executed by the data binding system? What is wrong with it?
In ADF all of the code and bindings in the JSP page are simply properties values used for ADF when it begins auto-generating code to link between JSP and the backing bean. So first and foremost I'm not sure (though I'm no expert) as to whether you can easily bind ADF components to just any collection.
Best bet to start with is to find a way to call a method directly early on that ensures the collection has been initialized, then refresh the table. Perhaps use a command button with full refresh so you don't have to worry about any PPR oddities.
Related
A similar question has been answered here:
How can I pass a runtime parameter as part of the dependency resolution?
However, I was wondering how this can be done when registering a generic class?
Normally, I would register it as following:
services.AddScoped(typeof(ITest<>), typeof(Test<>));
But what if I want to pass a runtime parameter to constructor? Without using DI, it would be something like:
new Test<MyClass>(string mystring, int myInt)
In the linked answer it's suggests using a factory method but this is giving me an error if I don't pass it the exact type.
The alternative would be to get an instance without passing a runtime parameter in the constructor and instead using a setter method after getting exact instance. I would like to avoid this however because every time after getting instance you must remember to call setter method.
Is there some way around it? I guess I could use some factory class instead of registering it in startup class...
EDIT:
After reading Steven's answer which was very useful, I updated question with more concrete example:
Following example is inside some method:
//instance of repository are passed inside constructor of class
//calling some to update/insert
//IMPORTANT - calling external service I want save parameters to db no matter what
using(var ctx=new DbContext())
{
//create log object
ctx.logs.add(Obj)
ctx.save()
}
//some code after
Let's say I want to be consistent and call method of my loggingrepository and there add logging object and save everything to database
However, every repository in constructor accepts DbContext, which is registered as scoped (durig one request).
If it's inside transaction, saving depends about code after calling external service and it can throw exception and save nothing.
So yeah, I could create new dbContext and pass it in logging method or call some private logging function and save inside it,
but point is that if I would ask for instance of loggingRepository I would want DI to pass this localy created dbContext variable to constructor
and not one registered as scoped inside startup method, so that addind and saving log happens no matter what external service or code after calling it does.
My situation in something similar, but it's going for some data in db based on current user and I don't wanna pass same parameter to numerous method, but only inside class constructor.
The general solution in injecting primitive configuration values into your application components, is to extract them into a Parameter Object. This gives those values a new, unambiguous type, which can be registered into your container:
// Parameter Object
public TestConfiguration
{
public string Mystring;
public int MyInt;
}
// (Generic) class using the Parameter Object
public class Test<T>
{
public Test(TestConfiguration config) { ... }
}
// Registering both
services.AddScoped(typeof(ITest<>), typeof(Test<>));
services.AddSingleton(new TestConfiguration { Mystring = ..., Myint = ... });
Configuration values are not considered to be runtime data as their values are known at startup and constant for the duration of the application. That's why you can supply them to the constructors of your application components.
Real runtime data, however, should not be passed on to a component during construction. Runtime data are values that are not known at startup and typically passed along by the user through a web request, are retrieved from the database, session, or anything that can change during the lifetime of the application.
Instead of passing runtime data in through the constructor, you should either:
Pass runtime data through method calls of the API or
Retrieve runtime data from specific abstractions that allow resolving runtime data.
You can find more information about passing runtime data here.
I'm still pretty new to JEE6 having come from a Servlets + JSP style of development on legacy systems. In the applications I worked on we would just throw objects into the various supplied scopes (request, session and application) keyed on a constant String. For example, the User object that represented the currently logged in user would be in the session scope keyed under "current_user".
I've done the same in our new JEE6 application, when the user logs in the User object is bound into the session scope. I'm wondering though if there is a better, more EE, way of handling this?
The problem I'm having is that now I've got the User stored in the session it's awkward to get access to it again. I can get it via JNDI look up or with a few lines of boiler plate code involving FacesContext but neither are very elegant.
Rather than boiler plate code all over the place (the User object is need in a few places) it would be great if I could just get the object injected into a field or method. After all there can only be one object in the session bound to a particular name so there shouldn't be any ambiguity about what I'm asking for. Is this possible?
Maybe the CDI could be of any help?
Could you define the way you achieve the User object into one, main method?
If so, and you're working with Java EE 6 environment, you could use the Producer method. Something between these lines:
public class ClassWhichCanAccessUserObject {
#Produces
public User produceUser() {
User u = ... // get the user as you do it right now
return u;
}
}
Then in the place you want to use this class you just Inject it (in the field or method) and use it:
public class MyLogic {
#Inject
User u;
}
You need to remember to add the beans.xml file to your classpath, as without the CDI will not work for your module.
I started messing with EF 4.0 because I am curious about the POCO possibilities... I wanted to simulate disconnected web environment and wrote the following code to simulate this:
Save a test object in the database.
Retrieve the test object
Dispose of the DataContext associated with the test object I used to retrieve it
Update the test object
Create a new data context and persist the changes on the test object that are automatically tracked within the DynamicProxy generated against my POCO object.
The problem is that when I call dataContext.SaveChanges in the Test method above, the updates are not applied. The testStore entity shows a status of "Modified" when I check its EntityStateTracker, but it is no longer modified when I view it within the new dataContext's Stores property. I would have thought that calling the Attach method on the new dataContext would also bring the object's "Modified" state over, but that appears to not be the case. Is there something I am missing? I am definitely working with self-tracking POCOs using DynamicProxies.
private static void SaveTestStore(string storeName = "TestStore")
{
using (var context = new DataContext())
{
Store newStore = context.Stores.CreateObject();
newStore.Name = storeName;
context.Stores.AddObject(newStore);
context.SaveChanges();
}
}
private static Store GetStore(string storeName = "TestStore")
{
using (var context = new DataContext())
{
return (from store in context.Stores
where store.Name == storeName
select store).SingleOrDefault();
}
}
[Test]
public void Test_Store_Update_Using_Different_DataContext()
{
SaveTestStore();
Store testStore = GetStore();
testStore.Name = "Updated";
using (var dataContext = new DataContext())
{
dataContext.Stores.Attach(testStore);
dataContext.SaveChanges(SaveOptions.DetectChangesBeforeSave);
}
Store updatedStore = GetStore("Updated");
Assert.IsNotNull(updatedStore);
}
As you stated later, you were using the POCO generator, not the self-tracking entities generator.
I've tried it as well, and became quite perplexed. It seems that the proxy classes don't quite work as expected, and there might be a bug. Then again. none of the examples on MSDN try something like this, and when they reference updates in different tiers of an app (something like we're doing here) they use self-tracking entities, not POCO proxies.
I'm not sure how these proxies work, but they do seem to store some kind of state (I managed to find the "Modified" state inside the private properties). But it seems that this property is COMPLETELY ignored. When you attach a property to a context, the context adds an entry to the ObjectStateManager, and it stores further state updates in there. At this point if you make a change - it will be registered, and applied.
The problem is that when you .Attach an entity - the Modified state from the proxy is not transferred to the state manager inside the context. Furthermore, if you use context.Refresh() the updates are override, and forgotten! Even if you pass RefreshMode.ClientWins into it. I tried setting the object state's state property to modified, but it was overridden anyway, and the original settings were restored..
It seems that there's a bug in the EF right not, and the only way to do this would be to use something like this:
using (var db = new Entities())
{
var newUser = (from u in db.Users
where u.Id == user.Id
select u).SingleOrDefault();
db.Users.ApplyCurrentValues(user);
db.SaveChanges();
}
One more thing here
Entitity Framework: Change tracking in SOA with POCO approach
It seems that POCO just doesn't support the approach you're looking for, and as I expected the self-tracking entities were created to tackle the situation you were testing, while POCO's proxies track changes only within the context they created.. Or so it seems...
Try
db.ObjectStateManager.ChangeObjectState(user, System.Data.EntityState.Modified);
Before calling SaveChanges
After playing around with the self-tracking entities, I realised what was your mistake.
Instead of trying to attach the entity to the data context, you should instead instruct that you want the data context to apply the new changes you have made to it to the database.
In this case, change the "saving" code to this:
using (var dataContext = new DataContext())
{
dataContext.Stores.ApplyChanges(testStore);
dataContext.SaveChanges();
}
At least I have tested it on my local machine, and it worked after this update :)
Hope this helps!
I think the root of your problem is your management of the Context object.
With POCO disposing the context does not notify the entities on that context that they are no longer associated with a context. The change tracking with POCO is all managed by the context so you get into some fun problems where the POCO will act like it is still attached to a context but in reality it is not and re-attaching to another context should throw an error about attaching to multiple contexts.
there is a small post about this you may want to read here:
http://social.msdn.microsoft.com/forums/en-US/adodotnetentityframework/thread/5ee5db93-f8f3-44ef-8615-5002949bea71/
If you switch to self tracking I think you'll find your entities work the way you're wanting.
another option is to add a property to a partial class of your poco to track changes manually after detaching the POCO from the context you used to load it.
I've just started using NHibernate, and I have some issues that I'm unsure how to solve correctly.
I started out creating a generic repository containing CUD and a couple of search methods. Each of these methods opens a separate session (and transaction if necessary) during the DB operation(s). The problem when doing this (as far as I can tell) is that I can't take advantage of lazy loading of related collections/objects.
As almost every entity relation has .Not.LazyLoad() in the fluent mapping, it results in the entire database being loaded when I request a list of all entities of a given type.
Correct me if I'm wrong, 'cause I'm still a complete newbie when it comes to NHibernate :)
What is most common to do to avoid this? Have one global static session that remains alive as long as the program runs, or what should I do?
Some of the repository code:
public T GetById(int id)
{
using (var session = NHibernateHelper.OpenSession())
{
return session.Get<T>(id);
}
}
Using the repository to get a Person
var person = m_PersonRepository.GetById(1); // works fine
var contactInfo = person.ContactInfo; // Throws exception with message:
// failed to lazily initialize a collection, no session or session was closed
Your question actually boils down to object caching and reuse. If you load a Foo object from one session, then can you keep hold of it and then at a later point in time lazy load its Bar property?
Each ISession instance is designed to represent a unit of work, and comes with a first level cache that will allow you to retrieve an object multiple times within that unit of work yet only have a single database hit. It is not thread-safe, and should definitely not be used as a static object in a WinForms application.
If you want to use an object when the session under which it was loaded has been disposed, then you need to associate it with a new session using Session.SaveOrUpdate(object) or Session.Update(object).
You can find all of this explained in chapter 10 of the Hibernate documentation.
If this seems inefficient, then look into second-level caching. This is provided at ISessionFactory level - your session factory can be static, and if you enable second-level caching this will effectively build an in-memory cache of much of your data. Second-level caching is only appropriate if there is no underlying service updating your data - if all database updates go via NHibernate, then it is safe.
Edit in light of code posted
Your session usage is at the wrong level - you are using it for a single database get, rather than a unit of work. In this case, your GetById method should take in a session which it uses, and the session instance should be managed at a higher level. Alternatively, your PersonRepository class should manage the session if you prefer, and you should instantiate and dispose an object of this type for each unit of work.
public T GetById(int id)
{
return m_session.Get<T>(id);
}
using (var repository = new PersonRepository())
{
var person = repository.GetById(1);
var contactInfo = person.ContactInfo;
} // make sure the repository Dispose method disposes the session.
The error message you are getting is because there is no longer a session to use to lazy load the collection - you've already disposed it.
I've got this Silverlight Prism application that is using MVVM. The model calls a WCF service and a list of data is returned.
The ViewModel is bound to the View, so the ViewModel should have a List property.
Were should I keep data returned by a WCF service in MVVM?
Should the List property be calling into the Model using its getter? Where the model has a ReturnListOfData() method that returns the data stored in the model.
Or does the ViewModel stores the data after the Model is done with calling the server?
This is a follow up on Where to put the calls to WCF or other webservices in MVVM?
Generally if I need to keep the Model objects around (I consider most things coming back from a WCF service a Model object) I will store it in my ViewModel in a "Model" property.
I've seen people go so far as to create a standard Model property on their base ViewModel type, like this (I don't do this, but it's nice):
public class ViewModel<ModelType> : INotifyPropertyChanged ...
{
//Model Property
public ModelType Model
{
...
}
}
It's really up to you. Keeping them as close to their related ViewModels is probably the thing to take away here.
It really depends on other aspects of your application. E.g. how's the data returned by ReturnListOfData() used? Are there other components interested in it? Does user update elements in the list? Can it create new elements that he'll want to save later? etc.
In the simplest case you'd just have a List property exposed by your viewmodel to view, and you'd reset that list to whatever ReturnListOfData() returned. It will probably work for a case when user simply performs a search, doesn't do anything to the data later on, and there's only one view that is interested in that data.
But suppose a user wants to be able to modify elements of that list. Clearly, you'll have to somehow track the changes in that original list, so then when user clicks save (or cancel), you'd send to the server only elements that were changed (or added) or restore the original elements if user clicks cancel. In this case you'd need a Model object, that would keep the original data, so then your viewmodel contains only its copy.