I have a JpaRepository with a custom method to find an object by ID and load children with an entity graph, e.g.
#EntityGraph(value="Parent.children", type = EntityGraphType.FETCH)
public Parent findByIdAndLoadChildren(Long id);
I want to cache the query using #Cacheable. The problem is that it won't cache the children. Any suggestion on how I can get Spring to cache the children?
Related
Question
Is there any way to make it so that an entity returned from a DbContext query returns null (or some other specific value) when you try to access a navigation property that you did not specificly .Include()? For example:
var parents = dbContext.People.Where(p => p.Children.Any()).Include("Children").ToList();
//Assert all parents have children...
Assert.IsTrue(parents[0].Children.Any());
And...
var parents = dbContext.People.Where(p => p.Children.Any()).ToList();
//Assert all children collections are null... NOT LAZY LOADED
Assert.IsTrue(parents[0].Children == null);
To be clear, I do not want the property to be Eager-Loaded. I don't want it to be loaded at all. I've tried Detaching the entity from the context, but this doesn't help.
Background
The reason I am trying to do this is because i need to access the entity object on a diffrent thread than the one the DbContext was created on. Because of this, I do NOT want the navigation property to be set to some defered excution linq statement. The problem is that since I cannot access DbContext to check if a navigation property is loaded or not (due to it not being thread safe) I have no way of knowing if I need to create a new DbContext on the current thread to retrieve the missing data. This is the same problem that I was trying to solve with How to tell if a Navigation Property is loaded without DbContext
Update
Setting the DbContext's Configuration.LazyLoadingEnabled property to false prevents the linq from getting auto-wired up, but for navigation properties that are collections this results in a empty collection rather than null.
To solve the collection based problem, I Modified my T4 template to generate an empty default constructor rather than one that set each ICollection equal to an empty HashSet.
You can enable / disable lazy-loading by setting the Configuration.LazyLoadingEnabled property of your DbContext
context.Configuration.LazyLoadingEnabled = false;
var parents = dbContext.People.Where(p => p.Children.Any()).ToList();
context.Configuration.LazyLoadingEnabled = true;
I am using JSF-2.2, Primefaces-3.5 and JDK-1.7.
I have a Registration Page where i have a Parent-Child Menu Relations on Countries and Cities, that needs to be loaded dynamically,based on the selected parent value.
Currently i am displaying the list of Countries and States! Which works like a charm! :)
How to display list of countries and cities in JSF
My Problem is if we have n-users accessing the page we are creating n-Objects which is load on the server. I want to reduce the load and memory wastage
Is there a way to Load Data and store in Context of Application and access them in JSF.
Useful Reference:
How to Populate Child Menus in JSF
You can just make the bean from Balusc's answer #ApplicationScoped, and only use this bean for reading the codelists. You can then inject the bean in your other beans, or just call it directly from the xhtml.
Cities you can also load in init() and keep in a Map<String, List<String>>, where key is country and value is cities. Or you can lazy initialize the cities:
Map<String, List<String>> map = new HashMap<>();
public synchronized List<String> getCities(String country) {
if (!map.containsKey(country)) {
List<String> cities = someService.getCities(country);
map.put(country, cities);
return cities;
}
return map.get(country);
}
However, if it at all is possible that the entries can change over time (other system updating/deleting in DB for example) #SessionScoped might be better, since you won't have to remember to reload the application/restart the server as with #ApplicationScoped.
I'm working on a JSF webapp which purpose is to wrap a command-line program.
One of its main functionality is the ability to share a session between users (eg. for courses purpose), so that when an input is sent to an instance of the application, the output sent to every subscriber for this session.
As a result of this design, the webapp is mainly composed of a view-scoped bean which will request a controller of the command-line application.
It has also been chosen to identify a session with the URL fragment (eg. mydomain/myapp/#SESSIONID), so that anyone using the URL with the same fragment will share inputs and outputs, using its own instance of the view-scoped bean but sharing the same controller
In order to push results to all subscribers, I'm using Primefaces Push. Results are primarily text that has to be appened to the webapp's terminal, but some commands lead to the programmatic creation of a JSF component.
In order to handle this, I just render these components to a string that I send to all subscribers.
Then, I realized that in order to handle ajax requests from components (and from every subscriber), the associated UIComponent needs to be added to the UIViewRoot in the context of (don't know how to express this) each view-scope bean.
As a matter of fact, I first tried to bind a "common container" (a UIForm) to a property of the view scoped bean, in which I would put the programmatically created components, but I obviously had to face the chicken/egg issue #BalusC talks about in his blog, because the component was added again on each ajax request. Setting javax.faces.PARTIAL_STATE_SAVING to false didn't help either (I'm using MyFaces 2.2.5)
So, as somewhat of a workaround, when the controller needs to create a new component, it basically adds the id of the component to the data pushed (in a HashMap converted to Json), and all subscribers will trigger (back) a remoteCommand to its own instance of the view-scoped bean, in order to update the "common container" from its own UIViewRoot.
This does work, but I don't like this way of doing it!
So:
would it be possible to handle this kind of sharing between view-scope beans (with the same name) which are stored in different HTTP sessions? I'm refering to this answer from #BalusC... maybe playing with javax.faces.ViewState - would it even be possible?
Is there a "magical" scope for my currently-view-scoped bean I could use?
Shall I rather use a completely different design?
Thanks!
If you want share data between all your application users you can use application scope.
If you still want to use view scope, you can connect your view scope with another application scope like this:
ApplicationView appView = BeanUtil.findBean("applicationView", FacesContext.getCurrentInstance());
import javax.faces.context.FacesContext;
public class BeanUtil {
#SuppressWarnings("unchecked")
public static <T> T findBean(String beanName, FacesContext context) {
return (T) context.getApplication().evaluateExpressionGet(context,
"#{" + beanName + "}", Object.class);
}
}
During testing a weakness was exposed in how our app builds f:selectItems lists, specifically, entering really long names on some of our entities screws page alignment by making really wide selects.
Many of these selectItem lists are duplicated in multiple views and backing beans, so I'd like to consolidate their creation.
We already have an application scoped bean that provides List<SelectItem> for enums, and my initial thought was to place them there.
I have some questions, though. We're using jsf 1.2 (if that matters)
1) My understanding is that application scoped beans are singleton simply because a single instance is instantiated and placed in session context. They are not like EJB3 singletons in that only one thread can access any method, so multiple requests won't block trying to access different methods. Is that correct?
2) I suspect each method would have to be synchronized to prevent multiple threads calling the same method from clobbering each other. Is that the case even if the only class member accessed in the method is a threadsafe stateless #EJB?
Following is an implementation of one of them that would be used in 20 views. The implementations for 10 other entities would be similar. Also, the appropriate converters are registered.
public synchronized List<SelectItem> getAccountSelect(){
List<Account> list = new ArrayList<Account>(pemEJB.list(Account.class));
Collections.sort(list, new AccountByActiveByName());
List<SelectItem> result=new ArrayList<SelectItem>(list.size());
for(Account row : list){
result.add(new SelectItem(row,
StringUtil.prefixTruncate(row.getName(), MAX_ACCT_LENGTH, row.isActive())));
}
return result;
}
Any advice appreciated
If it's really mandatory to do the data loading in a getter instead of in the constructor/postconstruct, then there's definitely no point of making it an application scoped bean. Just make it a request scoped one where you do the data loading job in the constructor/postconstruct.
In the jsf applications I work on we load almost all of our reference data (values for selectOneMenues primarily) in Application scope beans and we set up the values in the Constructor of those beans. The data is then available to other managed beans and views via getters but is globalized and centralized for the application. Since the values are only read via getters there is no need for synchronization.
We then expose the beans as mbeans through jmx with a reload method so that they can be updated as needed. The reload method(s) are synchronized so as to block during the short reloads.
In your example above it seems like you could just return a Collection of selectItems so as long as the values are setup in advance you can use this method and still serve multiple threads just fine:
public List<SelectItem> getAccountSelectItems() {
return this.accountSelectItems;
}
Just add this private member to your bean:
private List<SelectItem> accountSelectItems;
and set it up in the constructor:
public AccountBean() {
List<Account> list = new ArrayList<Account>(pemEJB.list(Account.class));
Collections.sort(list, new AccountByActiveByName());
this.accountSelectItems = new ArrayList<SelectItem>(list.size());
for(Account row : list) {
this.accountSelectItems.add(new SelectItem(row, StringUtil.prefixTruncate(row.getName(), MAX_ACCT_LENGTH, row.isActive())));
}
}
If on the other hand this is data that is constantly changing and needs to be updated you might be better off just loading it per session or per request, though you can reload it periodically in application scope using Quartz or some other timer to keep the data reads from your data source down if real time is not an essential requirement for this data in your app. If you are reloading the data then you will want to synchronize those operations if you're using application scope.
Hi I have a question about best practices vs safe programming in building a JSF Web Applicaiton.
I have employee.xhtml page having backing Bean - EmployeeBean. All the variables that I declare in the backing bean are non static and have getter and setter methods. For example:
ArrayList <Employee> alEmployees = new ArrayList<Employee>();
int userId;
The constructor of the BackingBean loads the employees. I acheive this by calling a static method in delegate.
userId = //some value.
alEmployees = EmployeeDelegate.loadEmployees(userId);
The Delegate method calls a static method in DAO Class.
Will the static methods cause any data concurrency issues when n users are using the application at same time? I mean userId 56 seeing userId 75 list when both are using the application same time?
Is it really advisable to have static methods in Delegate and DAO layer?
Please let me know if I was not clear.
Thanks
If the EmployeeDelegate does not hold any class variables which is sensitive to changes caused by method calls and/or has influence on how methods behave, then it's safe to do so.
You however have another major problem with this approach. The delegate should be an interface so that you can easily substitute it with a different implementation. This approach suggests that the delegate is not an interface at all (since it can impossibly have static methods).