Just learning nhibernate with fluent, and my session provider looks like:
public class SessionProvider
{
private static ISessionFactory sessionFactory;
public static ISessionFactory SessionFactory
{
get
{
if (sessionFactory == null)
{
sessionFactory = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2005.ConnectionString( c => c.FromAppSetting("sqlserver")))
.Mappings( m => m.FluentMappings.AddFromAssemblyOf<UserMapping>())
.BuildSessionFactory();
}
return sessionFactory;
}
}
private SessionProvider()
{ }
public static ISession GetSession()
{
return SessionFactory.OpenSession();
}
}
Is this how I should be getting my session object? Is this the 'fastest' way to do this for a high traffic website?
As a side note here is an short post on the cost of creating a new session by one of the NHibernate devs (spoiler: It's cheap)
What is the cost of opening a session
The "fastest" would be to simply keep 1 session for the whole app-lifecycle, but that would also be rather stupid :P (Well, with multicore nowadays, I'm not even sure if that's the fastest).
Everything seems fine. Just remember that GetSession() opens a new session on each call. Personally, I like to keep 1 session per HttpRequest, aka.:
public static ISession GetSession()
{
if (HttpContext.Current.Items[SESSION_KEY] == null)
{
HttpContext.Current.Items[SESSION_KEY] = SessionFactory.OpenSession();
}
return HttpContext.Current.Items[SESSION_KEY] as ISession;
}
private const string SESSION_KEY = "kahsdmiashdohbasduhfasduybadsubdsabsd";
You could also do checks on the state of your session (closed, dirty, open?), and act accordingly, instead of just the "lazy-initialization".
[EDIT] BTW, it seems like you don't want to have your class instantiated (private constructor, all static members). You should declare the class as static, e.g. public static class MyClass{} . This will make it so that the class can't contain non-static members and can't be instantiated.
Related
I am calling a function which has CacheEvict annotation on it. This is being called from a function that is itself executed asynchronously.
It seems that the cache is not being evicted after the function has been executed.
Here is sample code
#Async("executor1")
public void function1()
{
// do something
anotherFunction("name", 123, 12);
// do something more
}
#CacheEvict(cacheNames = {"cache1", "cache2", "cache3"}, key = "#testId")
public List<Integer> anotherFunction(String name, int testId, int packageId)
{
// some code here
}
What I want is that entries corresponding to testId should be cleared from all the caches.
However, in another call, I can see old entries of cache1. function1 is being called from the controller. Both these functions are present inside the service. Now, Is this configuration correct? If yes, What may be the possible reasons that cache is not being cleared?
Any help appreciated. Thanks in advance.
I think your problem is that Spring proxies are not reentrant. To implement Async and CacheEvict, Spring creates a proxy. So, in your example, the call stack will be:
A -> B$$proxy.function1() -> B.function1() -> B.anotherFunction()
B$$proxy contains the logic for async and eviction. Which won't apply when calling directly anotherFunction. In fact, even if you remove the #Async, it will still don't work.
A trick you can use is to inject the proxied bean into the class. To delegate to the proxy of the class instead this.
public class MyClass {
private MyClass meWithAProxy;
#Autowired
ApplicationContext applicationContext;
#PostConstruct
public void init() {
meWithAProxy = applicationContext.getBean(MyClass.class);
}
#Async("executor1")
public void function1() {
meWithAProxy.anotherFunction("name", 123, 12);
}
#CacheEvict(cacheNames = "cache1", key = "#testId")
public List<Integer> anotherFunction(String name, int testId, int packageId) {
return Collections.emptyList();
}
}
It works. But there's a catch. If you now call anotherFunction directly, it won't work. I consider this to be a Spring bug and will file it as is.
consider the following scenario: i have a bean that handles user-searches with a lot of parameters used on many pages with different urls. many users may spent a larger time with custom-searches and currently i am hitting the database to load those static lists everytime.
#ManagedBean
#ViewScoped
public class SearchBean extends DefaultBean {
private String searchPath; //seo: build a url-friendly path depending on search-parameters
private List<Currency>currencies;
private List<Country>countries;
private List<Market>markets;
private List<DrugTypes>drugTypes;
private List<Products>products;
/**
* ...15 other lists
*/
private List<ResultData>results;
#PostConstruct
public void init(){
this.currencies = Currency.getAll(); //jpa-entities
this.countries = Country.getAll();
this.markets = Markets.getAll();
this.drugTypes = DrugTypes.getAll();
this.products = Products.getAll();
}
public String search(){
this.results = ResultData.getByParameters(getSearchParams());
//
//e.g. localhost:8080/myApp/search/markets/germany/class-alpha-products/rhesus?faces-redirect=true
return searchPath;
}
public List<Currency> getCurrencies() { return currencies; }
public void setCurrencies(List<Currency> currencies) { this.currencies = currencies; }
public List<Country> getCountries() { return countries; }
public void setCountries(List<Country> countries) { this.countries = countries; }
public void setMarkets(List<Market> markets) { this.markets = markets; }
public List<Market> getMarkets() { return markets; }
public void setDrugTypes(List<DrugTypes> drugTypes) { this.drugTypes = drugTypes; }
public List<DrugTypes> getDrugTypes() { return drugTypes; }
public List<Products> getProducts() { return products; }
public void setProducts(List<Products> products) { this.products = products; }
}
what is the recommend way regarding to the headline? my small gripe is, that i see 20 jpa-queries on the console although the list-data which is build with <h:selectOneMenu> on client-side does not change on new pages but must be included on every subpage.
leave it as it is
put all those lists as session-attributes and remove them in #predestroy when user leaves.
put the whole bean as sessionbean (i already have 2 session-beans ("user" and "language" and i read that having more is not a good design)
store the list-data as a json-string in a cookie and recreate the list if the cookie exists?
other suggestions?
thanks for watching!
None of all. Caching DB entities isn't the responsibility of a front end (UI) framework. That's the responsibility of the persistence (DB) framework, which is thus JPA in your case.
JPA offers 2nd level caching possibilities. Main advantage as compared to all your proposals is that it knows precisely which entities are more queried and thus need to be cached, and when exactly to invalidate a cached entity because of an entity change. JSF as being a dumb HTML form based MVC framework which only delegates user interface events/data to business services knows nothing of this all.
See also:
How to configure L2 cache in Hibernate/JPA2?
Hibernate 5.1 User Guide - Chapter 12: Caching
EclipseLink Wiki - Examples / JPA / Caching
I am looking for transportation layer for gwt. I would like to create ajax request using generic method, f.e this is my DAO/service:
public class GenericDao<T extends GenericModel<T>> {
private Logger logger = LoggerFactory.getLogger(this.getClass().getCanonicalName());
#Transient protected Class<T> entityClass;
public GenericDao() {
super();
}
public GenericDao(Class<? extends GenericModel<T>> clazz) {
this.entityClass = (Class<T>) clazz;
}
public T getBy(Long id) {
return JPA.em().find(entityClass, id);
}
public List<GenericModel<T>> get() {
logger.error("trying to get data from db");
return getList();
}
public List<GenericModel<T>> getList() {
return JPA.em().createQuery("FROM " + entityClass.getSimpleName()).getResultList();
}
public void save(GenericModel<T> entityClass) {
JPA.em().getTransaction().begin();
JPA.em().persist(entityClass);
JPA.em().getTransaction().commit();
}
public void update(T entityClass) {
JPA.em().getTransaction().begin();
JPA.em().merge(entityClass);
JPA.em().getTransaction().commit();
}
public void delete(T entityClass) {
JPA.em().getTransaction().begin();
JPA.em().remove(entityClass);
JPA.em().getTransaction().commit();
}
}
GenericModel/Entity:
#MappedSuperclass
public class GenericModel<T extends GenericModel<T>> implements Identifiable, Versionable {
#Transient
protected Class<T> entityClass;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Version
private Integer version;
// setter & getter
#Override
public Long getId() {return id;}
public void setId(Long id) {this.id = id;}
#Override
public Integer getVersion() {return version;}
public void setVersion(Integer version) {this.version = version;}
// constructor
public GenericModel() {
Class<?> obtainedClass = getClass();
Type genericSuperclass = null;
for (;;) {
genericSuperclass = obtainedClass.getGenericSuperclass();
if (genericSuperclass instanceof ParameterizedType) {
break;
}
obtainedClass = obtainedClass.getSuperclass();
}
ParameterizedType genericSuperclass_ = (ParameterizedType) genericSuperclass;
try {
entityClass = ((Class) ((Class) genericSuperclass_
.getActualTypeArguments()[0]));
} catch (ClassCastException e) {
entityClass = guessEntityClassFromTypeParametersClassTypedArgument();
}
}
public GenericModel(Long id) {
this();
this.id = id;
}
}
I am looking for mechanism that will allow me to use this generic service for all models on client side (each db entity have id- so I would like to downloads using ajax all my Entities this way, so I should have only one generic method for that on client side).
I've already checked:
GWT-RPC
RequestFactory
RestyGWT
But none of them support this feature.
I've found here:
https://www.mail-archive.com/google-web-toolkit#googlegroups.com/msg100095.html
information that: gwt-jackson supports generics and polymorphism. Unfortunately I didn't found any working example that. Can someone help, give an example, approved that information?
All entities have id and version parameter. So I would like to have one metod on client side RF that will allow me to get from server(service/dao/whatever) that entity by id- like this: Request getBy(Long id); But unfortunatelly I can't make it work. I like the RF way, so I've tried it first. Generally I don't wonna repeat code for downloading entity/proxy by id.
For better understanding, please look also on:
RequestFactory client-side inheritance of typed class with generics
I'm confused as to why you think RPC can't handle generics - according to your link, it can, but RestyGWT cannot. Granted, none of your JPA references make any sense in GWT, but those would live in a DAO on the server, not in the entity/model class themselves, or at least not in the client version. If you had a RPC method that returned T where <T extends GenericModel<T>>, then you would have serializers for every possible GenericModel<?> subtype, and any/all that are gwt-compatible could be sent over the wire.
Edit from update to question:
Your GenericModel class uses features of Java that cannot work in GWT, such as reflection. This cannot be compiled to GWT, since the compiler relies on removing reflection information to minimize your compiled size - leaving in general reflection information means leaving in details about all classes and members, even ones that it can't statically prove are in use, since some reflection might make use of them.
If there is a way to phrase your model object in a way that just deals with the data at hand, focus on that. Otherwise consider a DTO which is just the data to send over the wire - I'm not sure how you would plan to use the entityClass field on the client, or why that would be important to read from the superclass's generics instead of just using getClass().
RequestFactory will have a hard time dealing with generics - unlike RPC (and possibly RestyGWT) it cannot handle polymorphism the way you want, but will instead only send the fields for the declared type, not any arbitrary subtype. RPC will actually send the instance if it is something that the client can handle.
I've Spring cache implemented as below
#Component
public class KPCacheExample {
private static final Logger LOG = LoggerFactory.getLogger(KPCacheExample.class);
#CachePut(value="kpCache")
public String saveCache(String userName, String password){
LOG.info("Called saveCache");
return userName;
}
#Cacheable(value="kpCache")
public String getCache(String userName, String password){
LOG.info("Called getCache");
return "kp";
}
}
And Java Config file
#Configuration
#ComponentScan(basePackages={"com.kp"})
public class GuavaCacheConfiguration {
#Bean
public CacheManager cacheManager() {
GuavaCacheManager guavaCacheManager = new GuavaCacheManager("kpCache");
guavaCacheManager.setCacheBuilder(CacheBuilder.newBuilder().expireAfterAccess(2000, TimeUnit.MILLISECONDS).removalListener(new KPRemovalListener()));
return guavaCacheManager;
}
}
By default the spring uses put method in the cache interface to update/put values in the cache. How can I force the spring to use putifabsent method to be invoked, such that I can get null value if cache is missed or in other wards first request to the method with unique username and password should return null and subsequent request to that username and password should return username.
Well, looking through Spring's Cache Abstraction source, there does not appear to be a configuration setting (switch) to default the #CachePut to use the "atomic" putIfAbsent operation.
You might be able to simulate the "putIfAbsent" using the unless (or condition) attribute(s) of the #CachePut annotation, something like (based on the Guava impl)...
#CachePut(value="Users", key="#user.name" unless="#root.caches[0].getIfPresent(#user.name) != null")
public User save(User user){
return userRepo.save(user);
}
Also note, I did not test this expression, and it would not be "atomic" or portable using a different Cache impl. The expression ("#root.caches[0].get(#user.name) != null") maybe more portable.
Giving up the "atomic" property may not be desirable so you could also extend the (Guava)CacheManager to return a "custom" Cache (based on GuavaCache) that overrides the put operation to delegate to "putIfAbsent" instead...
class CustomGuavaCache extends GuavaCache {
CustomGuavaCache(String name, com.google.common.cache.Cache<Object, Object> cache, boolean allowNullValues) {
super(name, cache, allowNullValues);
}
#Override
public void put(Object key, Object value) {
putIfAbsent(key, value);
}
}
See the GuavaCache class for more details.
Then...
class CustomGuavaCacheManager extends GuavaCacheManager {
#Override
protected Cache createGuavaCache(String name) {
return new CustomGuavaCache(name, createNativeGuavaCache(name), isAllowNullValues());
}
}
See GuavaCacheManager for further details, and specifically, have a look at line 93 and createGuavaCache(String name).
Hope this helps, or at least gives you some more ideas.
I use Windor Castle to wrap the HttpContext into a HttpContextWrapper via a factory method.
container.Register(
Component.For<HttpContextBase>()
.LifeStyle.PerWebRequest
.UsingFactoryMethod(() => new HttpContextWrapper(HttpContext.Current)));
I have a class called SessionStorage which accesses HttpContext.Current.Session. I register it this way:
container.Register(
Component.For<ISessionStorage>()
.LifeStyle.PerWebRequest
.ImplementedBy<HttpSessionStorage>());
The HttpSessionStorage class:
public class HttpSessionStorage : ISessionStorage
{
public HttpContextBase httpContext { get; set; }
public void Remove(string key)
{
httpContext.Session.Remove(key);
}
public T Get<T>(string key)
{
return (T)httpContext.Session[key];
}
public void Set<T>(string key, T value)
{
httpContext.Session[key] = value;
}
}
When I use it this way, then in about 40% of the cases the Session property is null and only if the requests are at a very high rate.
The strange thing is that if I use HttpContext.Current instead of httpContext, it works in all cases.
public class HttpSessionStorage : ISessionStorage
{
public HttpContextBase httpContext { get; set; }
public void Remove(string key)
{
HttpContext.Current.Session.Remove(key);
}
public T Get<T>(string key)
{
return (T)HttpContext.Current.Session[key];
}
public void Set<T>(string key, T value)
{
HttpContext.Current.Session[key] = value;
}
}
It has something to do with Windsor Castle but I can't find the problem. I registered everything I can as PerWebRequest (except a NHibernate session factory).
Does someone have an idea what else I could check?
Lg
warappa
OK, it wasn't due to inproper Castle Windsor registration but something simpler: I accessed Session at a time when it's not garanteed to be fully initialized - dummy me!
My solution was to move the Session accessing code from Application_BeginRequest to Application_AcquireRequestState like pointed out here.
Note:
Maybe this code should be moved into a base controller - in OnAuthorization (edit: it works!).
I had similar problems a while back, maybe the answers to my question can help you: ASP.NET MVC & Windsor.Castle: working with HttpContext-dependent services