I want to use the memcache in google app engine and i implemented like this :
public static UserDictionary userDictionary = null;
private MemcacheService syncCache;
public static final Logger log = Logger.getLogger(UserDictionary.class.getName());
#SuppressWarnings(value = { "unchecked" })
private UserDictionary() {
syncCache = MemcacheServiceFactory.getMemcacheService();
syncCache.setErrorHandler(ErrorHandlers.getConsistentLogAndContinue(Level.INFO));
}
public static UserDictionary getInstance() {
if(userDictionary == null) {
userDictionary = new UserDictionary();
}
return userDictionary;
}
public Entity getFromCache(String userId) {
return (Entity) syncCache.get(userId);
}
public void putInCache(String userId, Entity userEntity) {
syncCache.put(userId, userEntity,Expiration.byDeltaSeconds(999999999), MemcacheService.SetPolicy.SET_ALWAYS);
}
public boolean isCacheEmpty() {
long itemCount = syncCache.getStatistics().getItemCount();
return itemCount == 0L;
}
The problem is that after i put an Object in cache and then i try to get it, the get method return null. I looked in my google app engine and it shows that is an object in memcache.The key is a java String. Both key and value implements Serializable.
Hit count: 0
Miss count: 31522
Hit ratio: 0%
Item count: 15 item(s)
Related
I am using the extension:
services.AddOidcStateDataFormatterCache();
in Asp.Net Core, to store the state in the distributed cache which is implemented using Redis:
services.AddStackExchangeRedisCache(options => {
options.Configuration = Configuration[RedisConnection];
});
but it seems that the entries in the Redis cache are not set with TTL:
Is there a setting to control the TTL of the keys that get created in the cache?
Already reported. Waiting for response. (Please, mention that you need this, there too!)
For the moment we use an ugly inheritor. Ugly because the base has no virtual methods and in addition requires a helper internal class ConfigureOpenIdConnectOptionsTTL : IPostConfigureOptions<OpenIdConnectOptions> (mostly copy&paste again) but at least it fixed "slow redis in production".
public class DistributedCacheStateDataFormatterTTL:
DistributedCacheStateDataFormatter, ISecureDataFormat<AuthenticationProperties>
{
public static readonly TimeSpan DefaultCacheDuration = TimeSpan.FromMinutes(5);
private readonly IHttpContextAccessor _httpContext;
private readonly string _name;
public DistributedCacheStateDataFormatterTTL(
IHttpContextAccessor httpContext, string name) : base(httpContext, name)
{
_httpContext = httpContext;
_name = name;
}
private string CacheKeyPrefix => "DistributedCacheStateDataFormatter";
private IDistributedCache Cache =>
_httpContext.HttpContext.RequestServices.GetRequiredService<IDistributedCache>();
private IDataProtector Protector =>
_httpContext.HttpContext.RequestServices
.GetRequiredService<IDataProtectionProvider>()
.CreateProtector(CacheKeyPrefix, _name);
string ISecureDataFormat<AuthenticationProperties>
.Protect(AuthenticationProperties data)
{
return ((ISecureDataFormat<AuthenticationProperties>)this).
Protect(data, string.Empty);
}
string ISecureDataFormat<AuthenticationProperties>
.Protect(AuthenticationProperties data, string purpose)
{
var key = Guid.NewGuid().ToString();
var cacheKey = $"{CacheKeyPrefix}-{purpose}-{key}";
var json = JsonConvert.SerializeObject(data, new JsonSerializerSettings()
{
DefaultValueHandling = DefaultValueHandling.Ignore,
NullValueHandling = NullValueHandling.Ignore
});
var options = new DistributedCacheEntryOptions();
if (data.ExpiresUtc.HasValue)
options.SetAbsoluteExpiration(data.ExpiresUtc.Value);
else
options.SetSlidingExpiration(DefaultCacheDuration);
// Rather than encrypt the full AuthenticationProperties
// cache the data and encrypt the key that points to the data
Cache.SetString(cacheKey, json, options);
return Protector.Protect(key);
}
}
internal class ConfigureOpenIdConnectOptionsTTL : IPostConfigureOptions<OpenIdConnectOptions>
{
private string[] _schemes;
private readonly IHttpContextAccessor _httpContextAccessor;
public ConfigureOpenIdConnectOptionsTTL(string[] schemes, IHttpContextAccessor httpContextAccessor)
{
_schemes = schemes ?? throw new ArgumentNullException(nameof(schemes));
_httpContextAccessor = httpContextAccessor ?? throw new ArgumentNullException(nameof(httpContextAccessor));
}
public void PostConfigure(string name, OpenIdConnectOptions options)
{
// no schemes means configure them all
if (_schemes.Length == 0 || _schemes.Contains(name))
{
options.StateDataFormat = new DistributedCacheStateDataFormatterTTL(_httpContextAccessor, name);
}
}
public static IServiceCollection AddOidcStateDataFormatterCache(
IServiceCollection services,
params string[] schemes)
{
services.RemoveAll<IPostConfigureOptions<OpenIdConnectOptions>>();
services.AddSingleton<IPostConfigureOptions<OpenIdConnectOptions>>(
svcs => new ConfigureOpenIdConnectOptionsTTL(
schemes,
svcs.GetRequiredService<IHttpContextAccessor>())
);
return services;
}
}
i am Trying to fit in breezeJS with my existing architecture. I have a structure like
html/JS/Angular :: based view using hot-towel angular.
web api controllers :: whom the view calls.
Services layer :: that is being called from Web api. Any business logic goes here.
Unit of Work :: And (if) business logic requires to talk to data base for CRUDs it calls UOW.
Repository Pattern :: UOW is actually wrapping repositories. and repositores in turn talking to DbContexts.
Uptill now i was able to conver normal repositories implementation into the one using
public EFContextProvider<MyContext> DbContext { get; set; }
instead of just DbContext and i am also exposing MetaData using a string property with in UOW and IQueryables are returned using DbContext.Context.SomeEntity
Question 1 : Am i on right track ??
Question 2 : Most of the breeze examples are suggesting one SaveChanges method that give you all the entities that were changed and it will persist it at once. What if i want to trigger some business logic before Add,Update and Delete. i want to call me AddSomething service method and want to have a particular type of entity being sent to AddSomething and run some business logic before persistence. How can i put it together.
my code looksl ike
[BreezeController]//This is the controller
public class BreezeController : ApiController
{
private readonly ISomeService someService;
public BreezeController(ISomeService someService)
{
this.someService = someService;
}
// ~/breeze/todos/Metadata
[HttpGet]
public string Metadata()
{
return someService.MetaData();
}
// ~/breeze/todos/Todos
// ~/breeze/todos/Todos?$filter=IsArchived eq false&$orderby=CreatedAt
[HttpGet]
public IQueryable<Node> Nodes()
{
return nodesService.GetAllNodes().AsQueryable();
}
// ~/breeze/todos/SaveChanges
//[HttpPost]
//public SaveResult SaveChanges(JObject saveBundle)
//{
// return _contextProvider.SaveChanges(saveBundle);
//}
Below is the service
public class SomeService : BaseService, ISomeService
{
private readonly IUow Uow;
public SomeService(IUow Uow)
: base(Uow)
{
this.Uow = Uow;
}
public IEnumerable<Something> GetAllNodes()
{
return Uow.Somethings.GetAll();
}
}
every service can expose one property through base. that is actually the meta data
public class BaseService : IBaseService
{
private readonly IUow Uow;
public BaseService(IUow Uow)
{
this.Uow = Uow;
}
public string MetaData()
{
return Uow.MetaData;
}
}
and the my UOW looks like
public class VNUow : IUow, IDisposable
{
public VNUow(IRepositoryProvider repositoryProvider)
{
CreateDbContext();
repositoryProvider.DbContext = DbContext;
RepositoryProvider = repositoryProvider;
}
// Code Camper repositories
public IRepository<Something> NodeGroup { get { return GetStandardRepo<Something>(); } }
} }
public IRepository<Node> Nodes { get { return GetStandardRepo<Node>(); } }
/// <summary>
/// Save pending changes to the database
/// </summary>
public void Commit()
{
//System.Diagnostics.Debug.WriteLine("Committed");
DbContext.Context.SaveChanges();
}
public string MetaData // the Name property
{
get
{
return DbContext.Metadata();
}
}
protected void CreateDbContext()
{
// DbContext = new VNContext();
DbContext = new EFContextProvider<VNContext>();
// Load navigation properties always if it is true
DbContext.Context.Configuration.LazyLoadingEnabled = false;
// Do NOT enable proxied entities, else serialization fails
DbContext.Context.Configuration.ProxyCreationEnabled = true;
// Because Web API will perform validation, we don't need/want EF to do so
DbContext.Context.Configuration.ValidateOnSaveEnabled = false;
//DbContext.Configuration.AutoDetectChangesEnabled = false;
// We won't use this performance tweak because we don't need
// the extra performance and, when autodetect is false,
// we'd have to be careful. We're not being that careful.
}
protected IRepositoryProvider RepositoryProvider { get; set; }
private IRepository<T> GetStandardRepo<T>() where T : class
{
return RepositoryProvider.GetRepositoryForEntityType<T>();
}
private T GetRepo<T>() where T : class
{
return RepositoryProvider.GetRepository<T>();
}
private EFContextProvider<VNContext> DbContext { get; set; }
#region IDisposable
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (DbContext != null)
{
DbContext.Context.Dispose();
}
}
}
#endregion
}
in the end Repository Implementaion looks like
public class EFRepository<T> : IRepository<T> where T : class
{
public EFRepository(EFContextProvider<VNContext> dbContext)
{
if (dbContext == null)
throw new ArgumentNullException("dbContext");
DbContext = dbContext;
DbSet = DbContext.Context.Set<T>();
}
protected EFContextProvider<VNContext> DbContext { get; set; }
protected DbSet<T> DbSet { get; set; }
public virtual IQueryable<T> GetAll()
{
return DbSet;
}
public virtual IQueryable<T> GetAllEagerLoad(params Expression<Func<T, object>>[] children)
{
children.ToList().ForEach(x => DbSet.Include(x).Load());
return DbSet;
}
public virtual IQueryable<T> GetAllEagerLoadSelective(string[] children)
{
foreach (var item in children)
{
DbSet.Include(item);
}
return DbSet;
}
public virtual IQueryable<T> GetAllLazyLoad()
{
return DbSet;
}
public virtual T GetById(int id)
{
//return DbSet.FirstOrDefault(PredicateBuilder.GetByIdPredicate<T>(id));
return DbSet.Find(id);
}
public virtual T GetByIdLazyLoad(int id, params Expression<Func<T, object>>[] children)
{
children.ToList().ForEach(x => DbSet.Include(x).Load());
return DbSet.Find(id);
}
public virtual void Add(T entity)
{
DbEntityEntry dbEntityEntry = DbContext.Context.Entry(entity);
if (dbEntityEntry.State != EntityState.Detached)
{
dbEntityEntry.State = EntityState.Added;
}
else
{
DbSet.Add(entity);
}
}
public virtual void Update(T entity)
{
DbEntityEntry dbEntityEntry = DbContext.Context.Entry(entity);
if (dbEntityEntry.State == EntityState.Detached)
{
DbSet.Attach(entity);
}
dbEntityEntry.State = EntityState.Modified;
}
public virtual void Delete(T entity)
{
DbEntityEntry dbEntityEntry = DbContext.Context.Entry(entity);
if (dbEntityEntry.State != EntityState.Deleted)
{
dbEntityEntry.State = EntityState.Deleted;
}
else
{
DbSet.Attach(entity);
DbSet.Remove(entity);
}
}
public virtual void Delete(int id)
{
var entity = GetById(id);
if (entity == null) return; // not found; assume already deleted.
Delete(entity);
}
}
Much of this question is broad question and answers will be primarily opinion based... that said, here's my two cents: keep it simple. Carefully consider whether you truly need 3, 4 and 5, especially whether you need to implement UoW or the Repository Pattern yourself. The EF DbContext implements both, you could use it in your controllers directly if you wanted.
If you have custom logic that needs to execute prior to savechanges utilize one of the interceptor methods: BeforeSaveEntity or BeforeSaveEntites. Here's the documentation for those methods:
http://www.getbreezenow.com/documentation/contextprovider#BeforeSaveEntity
Breeze supports "Named saves" where you specify the name of the specific server endpoint ( i.e. your service method) on a per save basis. See:
http://www.getbreezenow.com/documentation/saving-changes
This would look something like this on your client.
var saveOptions = new SaveOptions({ resourceName: "CustomSave1" });
em.saveChanges(entitiesToSave, saveOptions).then(function (saveResult) {
// .. do something interesting.
}
and on your server
[HttpPost]
public SaveResult CustomSave1(JObject saveBundle) {
ContextProvider.BeforeSaveEntityDelegate = CustomSave1Interceptor;
return ContextProvider.SaveChanges(saveBundle);
}
private Dictionary<Type, List<EntityInfo>> CustomSave1Interceptor(Dictionary<Type, List<EntityInfo>> saveMap) {
// In this method you can
// 1) validate entities in the saveMap and optionally throw an exception
// 2) update any of the entities in the saveMap
// 3) add new entities to the saveMap
// 4) delete entities from the save map.
// For example
List<EntityInfo> fooInfos;
if (!saveMap.TryGetValue(typeof(Foo), out fooEntities)) {
// modify or delete any of the fooEntites
// or add new entityInfo instances to the fooEntities list.
}
}
im trying to build a google app engine projekt with JPA, JAX-RS and JAX-B. My POST and GET Methods work, but my DELETE method doesn't delete the data.
Resource
#DELETE
#Path("card/{id}")
public void deleteCardById (#PathParam ("id") Long id) {
Service.removeCard(id);
}
Service
public static void removeCard(Long id) {
EntityManager em = EMFService.get().createEntityManager();
Card emp = findCard(id);
if (emp != null) {
em.remove(emp);
}
em.close();
}
public static Card findCard(Long id) {
EntityManager em = EMFService.get().createEntityManager();
Card card = em.find(Card.class, id);
em.close();
return card;
}
Entity
#XmlRootElement
#Entity
public class Card {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
Long id;
String begriff;
String tabu1;
String tabu2;
String tabu3;
public Card(String begriff, String tabu1, String tabu2, String tabu3) {
super();
Begriff = begriff;
Tabu1 = tabu1;
Tabu2 = tabu2;
Tabu3 = tabu3;
}
public Card() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getBegriff() {
return Begriff;
}
public void setBegriff(String begriff) {
Begriff = begriff;
}
public String getTabu1() {
return Tabu1;
}
public void setTabu1(String tabu1) {
Tabu1 = tabu1;
}
public String getTabu2() {
return Tabu2;
}
public void setTabu2(String tabu2) {
Tabu2 = tabu2;
}
public String getTabu3() {
return Tabu3;
}
public void setTabu3(String tabu3) {
Tabu3 = tabu3;
}
#Override
public String toString() {
return "Card [Begriff=" + Begriff + ", Tabu1=" + Tabu1 + ", Tabu2="
+ Tabu2 + ", Tabu3=" + Tabu3 + "]";
}
When i Debug the app it gives the correct Object to the remove function. But it just don't remove the data ...
You mean you're using v1 of the GAE JPA plugin, and you don't bother putting a transaction around your remove (so the remove is delayed until the next transaction ... which never happens)?
Obviously you could either put a transaction around the remove, or better still you use v2 of the GAE JPA plugin
I was facing similar issue too. the JPA delete actually deletes the entity in the datastore,but it doesn't delete the entity from the JPA Cache.. You page is actually using the JPA Cached result list to display..
The way I used to resolve the issue is to have the JPA Cache cleared every time after a delete.
Sample Code would be something like this:
EM.getTransaction().begin();
EM.remove(current_record);
EM.getTransaction().commit();
EM.getEntityManagerFactory().getCache().evictAll();
ok i think i should write it like this
*edit the problem was the findCard function, i think because of the secone instance of the EntityManager. I chnaged it without using this method to this and now it works.
public static void removeCard(Long id) {
EntityManager em = EMFService.get().createEntityManager();
EntityTransaction tx = em.getTransaction();
try {
tx.begin();
Card card = em.find(Card.class, id);
if (card != null) {
em.remove(card);
}
tx.commit();
} finally {
if (tx.isActive()) {
tx.rollback();
}
em.close();
}
}
How do I structure the database? I use a repository pattern with entity framework and code-first to code the models.
For example: I want an admin to set a string to be appended to every username.
I was thinking about a key-value table (settings) that has the following columns? SettingsId, Name, Value. With this method, I would need to manually go in, create a record Name:AppendedToUsername, Value:nil. I would then write repository methods specifically for each settings I need. For eg.
public string GetAppenedToUsername()
{
db.Settings.FirstOrDefault(s => s.Name == "AppendedToUsername").Select(s => s.Value);
}
Is there any better way of designing this database?
It's a good solution. I only recommend to create a strongly typed class with these settings and use caching for them.
Cache service:
public class CacheService
{
private ObjectCache Cache
{
get { return MemoryCache.Default; }
}
public object Get(string key)
{
return Cache[key];
}
public void Set(string key, object data, int cacheTime)
{
CacheItemPolicy policy = new CacheItemPolicy();
policy.AbsoluteExpiration = DateTime.Now.AddMinutes(cacheTime);
Cache.Add(new CacheItem(key, data), policy);
}
public bool IsSet(string key)
{
return (Cache[key] != null);
}
public void Invalidate(string key)
{
Cache.Remove(key);
}
}
AppSetting:
public class AppSetting
{
public const string StrSettingKey = "StrSetting";
private CacheService CacheService { get; set; }
private DbContext DbContext { get; set; }
public AppSetting(ICacheService cache, DbContext db)
{
CacheService = CacheService;
DbContext = db;
}
public string StrSetting
{
get
{
if (CacheService.IsSet(StrSettingKey))
{
return (string) CacheService.Get(StrSettingKey);
}
else
{
var value = DbContext.Settings.Single(s => s.Name == StrSettingKey).Select(s => s.Value);
CacheService.Set(StrSettingKey, value, 60); //one hour
return value;
}
}
set
{
var item = DbContext.Settings.Single(s => s.Name == StrSettingKey);
item.Value = value;
DbContext.SaveChanges();
CacheService.Set(StrSettingKey, value);
}
}
}
I want to define a SuggestBox, which behaves like the search bar in Google Maps: When you begin to type, real addresses, starting with the typed letters, appear.
I think, that I need to use the Geocoder.getLocations(String address, LocationCallback callback) method, but I have no idea how to connect this with the oracle, which is needed by the suggest box to produce its suggestions.
Can you please give me ideas how do I connect the getLocations Method with the SuggestOracle?
I solved this by implementing a subclass of SuggestBox, which has it's own SuggestOracle. The AddressOracle deals as a Wrapper for the Google Maps Service, for which the class Geocoderin the Google Maps API for GWT offers abstractions.
So here is my solution:
First we implement the Widget for a SuggestBox with Google Maps suggestions
public class GoogleMapsSuggestBox extends SuggestBox {
public GoogleMapsSuggestBox() {
super(new AddressOracle());
}
}
Then we implement the SuggestOracle, which wraps the Geocoder async method abstractions:
class AddressOracle extends SuggestOracle {
// this instance is needed, to call the getLocations-Service
private final Geocoder geocoder;
public AddressOracle() {
geocoder = new Geocoder();
}
#Override
public void requestSuggestions(final Request request,
final Callback callback) {
// this is the string, the user has typed so far
String addressQuery = request.getQuery();
// look up for suggestions, only if at least 2 letters have been typed
if (addressQuery.length() > 2) {
geocoder.getLocations(addressQuery, new LocationCallback() {
#Override
public void onFailure(int statusCode) {
// do nothing
}
#Override
public void onSuccess(JsArray<Placemark> places) {
// create an oracle response from the places, found by the
// getLocations-Service
Collection<Suggestion> result = new LinkedList<Suggestion>();
for (int i = 0; i < places.length(); i++) {
String address = places.get(i).getAddress();
AddressSuggestion newSuggestion = new AddressSuggestion(
address);
result.add(newSuggestion);
}
Response response = new Response(result);
callback.onSuggestionsReady(request, response);
}
});
} else {
Response response = new Response(
Collections.<Suggestion> emptyList());
callback.onSuggestionsReady(request, response);
}
}
}
And this is a special class for the oracle suggestions, which just represent a String with the delivered address.
class AddressSuggestion implements SuggestOracle.Suggestion, Serializable {
private static final long serialVersionUID = 1L;
String address;
public AddressSuggestion(String address) {
this.address = address;
}
#Override
public String getDisplayString() {
return this.address;
}
#Override
public String getReplacementString() {
return this.address;
}
}
Now you can bind the new widget into your web page by writing the following line in the onModuleLoad()-method of your EntryPoint-class:
RootPanel.get("hm-map").add(new GoogleMapsSuggestBox());