I'm creating a RequestQueue in a singleton class and the example provided by Google is creating it by a call of newRequestQueue of the Volley class that get as a parameter just the Context of the current application:
mRequestQueue = Volley.newRequestQueue(mCtx.getApplicationContext());
Previously I was not using a singleton class and I created a RequestQueue in the activity OnCreate with this code:
Cache cache = new DiskBasedCache(getCacheDir(), 1024 * 1024); // 1MB cap
// Set up the network to use HttpURLConnection as the HTTP client.
Network network = new BasicNetwork(new HurlStack());
// Instantiate the RequestQueue with the cache and network.
mRequestQueue = new RequestQueue(cache, network);
Because with this code I set network and cache I search for the Volley class for an appropriate newRequestQueue method but I noticed there is just two overloads of newRequestQueue, one with the HttpStack parameter that I can use to set the network, but there are not with a Cache parameter.
So the question is: there is a manner to create a RequestQueue with the Volley class costumizing its cache?
Related
I am unable to access a public container using the C# SDK, even though I have enabled "Allow Blob public access" in the storage account configuration.
var fileSystemClient = new DataLakeFileSystemClient(new Uri("https://somestorageaccount.dfs.core.windows.net/public"), new DataLakeClientOptions());
var paths = fileSystemClient.GetPaths();
foreach (var path in paths)
{
Console.WriteLine(path);
}
This code throws the following exception:
Azure.RequestFailedException: 'Server failed to authenticate the
request. Make sure the value of Authorization header is formed
correctly including the signature.
Is there anything I can configure to make this work?
I tried in my environment and got below results:
Initially, I created ADLS gen2 container with public access level set to container level.
Portal:
When I try to access the file through browser, I got same error.
Browser:
When we are accessing through file system, Files kept in storage system are not accessible anonymously. It is necessary to authorize access even if it is public Access level. You are getting this error because you are attempting to access the resource without authorization.
If you need to access files, you need to authorize with SAS token.
I tried with File URL + SAS token in the browser. I can be able to access the file.
You can get SAS-token by clicking file with generate SAS token.
Browser:
If you need access path of data lake gen 2 in C#, you use the StorageSharedKeyCredential method by this link:
string storageAccountName = StorageAccountName;
string storageAccountKey = StorageAccountKey;
Uri serviceUri = StorageAccountUri;
StorageSharedKeyCredential sharedKeyCredential = new StorageSharedKeyCredential(storageAccountName, storageAccountKey);
DataLakeServiceClient serviceClient = new DataLakeServiceClient(serviceUri, sharedKeyCredential);
DataLakeFileSystemClient filesystem = serviceClient.GetFileSystemClient(Randomize("sample-filesystem-list"));
List<string> names = new List<string>();
foreach (PathItem pathItem in filesystem.GetPaths())
{
names.Add(pathItem.Name);
}
Reference:
java - How to get list of child files/directories having parent DataLakeDirectoryClient class instance - Stack Overflow in java by Jim Xu.
My Application uses ElastiCache on AWS for caching purposes. Our current set up uses a basic Redis Cluster with no sharding or failover. We need to now move to a Clustered Redis Elastic Cache with sharding, failover etc enabled. Creating a new cluster on AWS was the easy bit, but we are a bit lost on how to modify our java code to reads and write from the cluster.
Current Implementation -
Initialize a JedisPool.
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxTotal(100);
jedisPoolConfig.setMaxIdle(10);
jedisPoolConfig.setMaxWaitMillis(50);
jedisPoolConfig.setTestOnBorrow(true);
String host = "mycache.db8e1v.0001.usw2.cache.amazonaws.com";
int port = 6379;
int timeout = 50;
JedisPool jedisPool = new JedisPool(jedisPoolConfig, host, port, timeout)
A Jedis object is borrowed from the pool everytime we need to perform an operation
Jedis jedis = JedisPool.getResource();
The new implementation would be
JedisPoolConfig jedisPoolConfig = ...
HostAndPort hostAndPort = new HostAndPort(host, port);
jedisCluster = new JedisCluster(Collections.singleton(hostAndPort), jedisPoolConfig);
Question:
The documentation says JedisCluster is to be used in place of Jedis (not JedisPool). Does this mean I need to create and destroy a JedisCluster object in each thread. Or can I re-use the same object and it will handle the thread safety? When do I exactly close the JedisCluster then? At the end of the application?
The JedisCluster holds internal JedisPools for each node in the cluster.
Does this mean I need to create and destroy a JedisCluster object in
each thread. Or can I re-use the same object and it will handle the
thread safety?
You can reuse the same object.
When do I exactly close the JedisCluster then? At the end of the
application?
Yes.
Replacing all Jedis-calls with JedisCluster-calls is the best way to migrate.
But I wanted pipeline support which JedisCluster currently lacks. So one other idea is to extend JedisCluster to return the JedisPool>Jedis for a particular key:
protected Jedis getJedis(String key) {
int slot = JedisClusterCRC16.getSlot(key);
return connectionHandler.getConnectionFromSlot(slot);
}
The extended class has to be in namespace redis.clients.jedis to access getConnectionFromSlot.
Now a pipeline can be executed on the Jedis.
And you need a different Jedis for each key you want to operate on. Which makes sense - in cluster mode, each key can be on a different node.
I'm trying to protect my webapi with IdentityServer and OpenID Connect using Autofac. I'm using OWIN. But for some reason I can't get claims of the user. It seems that AccessTokenValidation is not triggered at all. That makes me think there is something wrong in the order of my declarations at my startup. Here is my startup.
public class Startup {
public void Configuration(IAppBuilder appBuilder) {
// Add authentication
this.AddAuthentication(appBuilder);
HttpConfiguration config = new HttpConfiguration();
var container = CreateAutofacContainer();
var resolver = new AutofacWebApiDependencyResolver(container);
config.DependencyResolver = resolver;
WebApiConfig.Register(config);
config.EnsureInitialized();
// Register config - you can't add anything to pipeline after this
appBuilder.UseAutofacMiddleware(container);
appBuilder.UseAutofacWebApi(config);
appBuilder.UseWebApi(config);
}
private static IContainer CreateAutofacContainer() {
var autofacBuilder = new ContainerBuilder();
var assembly = Assembly.GetExecutingAssembly();
// Register your Web API controllers.
autofacBuilder.RegisterApiControllers(assembly);
// For general logging implementation
autofacBuilder.RegisterType<ConsoleLogger>().As<ILogger>();
// Create empty usage context to be filled in OWIN pipeline
IUsageContext usageContext = new RuntimeUsageContext();
autofacBuilder.RegisterInstance(usageContext).As<IUsageContext>().SingleInstance();
// We need to get usage context builded
autofacBuilder.RegisterType<OIDCUsageContextProvider>().InstancePerRequest();
var container = autofacBuilder.Build();
return container;
}
private void AddAuthentication(IAppBuilder app) {
var options = new IdentityServerBearerTokenAuthenticationOptions();
options.Authority = "MYAUTHORITY";
options.RequiredScopes = new[] { "openid", "profile", "email", "api" };
options.ValidationMode = ValidationMode.ValidationEndpoint;
app.UseIdentityServerBearerTokenAuthentication(options);
// Add local claims if needed
app.UseClaimsTransformation(incoming => {
// either add claims to incoming, or create new principal
var appPrincipal = new ClaimsPrincipal(incoming);
// incoming.Identities.First().AddClaim(new Claim("appSpecific", "some_value"));
return Task.FromResult(appPrincipal);
});
}
I'm using hybrid flow and api is called from SPA-application. I've verified (by calling my identity server's endpoint directly) that access token is valid and there are claims available. I also downloaded IdentityServer.AccessTokenValidation project and attached it as a reference. When I set some breakpoints to methods in that project, they never get called. That is why I think there is something wrong with my startup and OWIN pipeline.
I've declared UsageContext in my startup. It is a class I'm using to collect claims and some configuration settings - to be injected to actual controllers. I think it would be nice way to handle this, so in controllers there is always valid UsageContext available.
I've read a lot of samples and examples but still haven't found exactly same situation. I'll appreciate any attempts to point me into right direction.
Regards,
Borre
Could it be your registration of UsageContext as a Singleton? You mention this class contains claims, so this object should be resolved once pr http request - shouldn't it?
It turned out that there was some mysterious line in AccessTokenValidation - library that didn't work. I use that library to get claims. After changing the line everything seemed to work.
So basically my question is closed now and stuff works. But I'm still not totally convinced this is the right way to do this.
Thanks John for your comments!
I'm an android beginner and I want to make a login using volley library, but i don't
know how i can obtain the JSONObject response from my server and use it to check
login parameters and launch a specific activity if the user exist.
//assuming you are implementing this part from an activity.
//otherwise, replace “this” with relevant context
RequestQueue myQueue = queue = Volley.newRequestQueue(this);
//your server address
String url = "http://my-json-feed";
//Create your JSON object request
JsonObjectRequest jsObjRequest = new JsonObjectRequest
(Request.Method.GET, url, null, new Response.Listener() {
#Override
public void onResponse(JSONObject response) {
//process the server response here.
//use the “response” object for checking the login parameters, etc.
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
//Handle errors such as network failures,etc here
}
});
//add the request object to the Volley queue
myQueue.add(jsObjRequest);
The "onResponse()" is the callback function which will give you the json object returned by the server. Inside that function, use that response to do whatever you want (for your case, to check login parameters, etc.)
For details, look here: Request JSON
Another note:
If you are to use the VolleyQueue only in one or two activities, it's okay to create separate volley queues for those couple of activities. But, if you have lots of activities and all of them needs to use Volley, then it would be a very bad choice to create volley queues for each activity. It can cause you OutOfMemory exception in the worst case. You can consider creating a singleton VolleyQueue which will be used by the whole application (Creating an ApplicationController class and including the Volley singleton queue in it can be one way to do that).
I'm building a series of WCF Services that are going to be used by more than one application. Because of that I'm trying to define a common library to access WCF services.
Knowing that each service request made by different users should use a different Channel I'm thinking in cache the Channel per-request (HttpContext.Current.Items) and cache the ChannelFactory used to create the channel per Application (HttpApplication.Items) since I can create more than one channel with the same ChannelFactory.
However, I have a question regarding this cache mechanism when it comes to closing the ChannelFactory and Channel.
Do I need to close the Channel after it's used, at the end of the request, or is it ok to leave it there to be closed (?) when the context of that request dies?
What about ChannelFactory? Since each channel is associated with the ChannelFactory that created it, is it safe to keep the same ChannelFactory during the life of the application process (AppDomain)?
This is the code I'm using to manage this:
public class ServiceFactory
{
private static Dictionary<string, object> ListOfOpenedChannels
{
get
{
if (null == HttpContext.Current.Items[HttpContext.Current.Session.SessionID + "_ListOfOpenedChannels"])
{
HttpContext.Current.Items[HttpContext.Current.Session.SessionID + "_ListOfOpenedChannels"] = new Dictionary<string, object>();
}
return (Dictionary<string, object>)HttpContext.Current.Items[HttpContext.Current.Session.SessionID + "_ListOfOpenedChannels"];
}
set
{
HttpContext.Current.Items[HttpContext.Current.Session.SessionID + "_ListOfOpenedChannels"] = value;
}
}
public static T CreateServiceChannel<T>()
{
string key = typeof(T).Name;
if (ListOfOpenedChannels.ContainsKey(key))
{
return (T)ListOfOpenedChannels[key];
}
else
{
ChannelFactory<T> channelF = new ChannelFactory<T>("IUsuarioService");
T channel = channelF.CreateChannel();
ListOfOpenedChannels.Add(key, channel);
return channel;
}
}
}
Thanks!
Ideally close the channel as soon as you are done with it. This will place it back into the channel pool so it can be used by another worker thread.
Yes, the channel factory (the expensive bit) can remain for the lifetime of the application.
Update
As of .Net 4.5 there is a built in caching options for factories
ChannelFactory Caching .NET 4.5
This is an aside. Why are you using SessionID as a context key? The context.Items is unique per request. That is:
HttpContext.Current.Items[HttpContext.Current.Session.SessionID +"_ListOfOpenedChannels"]
should be functionally equivalent to:
HttpContext.Current.Items["ListOfOpenedChannels"]