Redis Cache - Access HMSET using Redisson - redis

I have HMSET stored in Redis Cache as below
>hmset [User1] [Key1] [value1] [Key2] [value2]
Now how do I get the key and value Map using User1 key in Redisson ? Also how to get value for specific key and user?
I tried
RMap<String, String> map = client.getMap( "User1" );
but it did not work.

RMap<String, String> map = client.getMap( "User1" );
This only provides you a handler to operate on the Redis hash object, you will need to invoke the get method to retrieve values of those fields you may require. For instance:
RMap<String, String> map = client.getMap( "User1" );
Object value1 = map.get("Key1");
Object value2 = map.get("Key2");

Related

How Spring store cache and key to Redis

I follow some tutorial on web to setup Spring Cache with redis,
my function look like this:
#Cacheable(value = "post-single", key = "#id", unless = "#result.shares < 500")
#GetMapping("/{id}")
public Post getPostByID(#PathVariable String id) throws PostNotFoundException {
log.info("get post with id {}", id);
return postService.getPostByID(id);
}
As I understand, the value inside #Cacheable is the cache name and key is the cache key inside that cache name. I also know Redis is an in-memory key/value store. But now I'm confused about how Spring will store cache name to Redis because looks like Redis only manages key and value, not cache name.
Looking for anyone who can explain to me.
Thanks in advance
Spring uses cache name as the key prefix when storing your data. For example, when you call your endpoint with id=1 you will see in Redis this key
post-single::1
You can customize the prefix format through CacheKeyPrefix class.

How can i get userId of aws account?

I am using a API call to retrieve the plaintext instance identity document. Here, accountId is present.
response = response.get("http://169.254.169.254/latest/dynamic/instance-identity/document").text
I am using the above code in my python script. How can i get AWS userId by API call?
Not sure if this is what you are after, but get_caller_identity returns UserId and Accountid:
UserId (string) The unique identifier of the calling entity. The exact value depends on the type of entity that is making the call. The
values returned are those listed in the aws:userid column in the
Principal table found on the Policy Variables reference page in the
IAM User Guide .
Account (string) The AWS account ID number of the account that owns or contains the calling entity.
Arn (string) The AWS ARN associated with the calling entity.
Example output is (from docs):
'Account': '123456789012',
'Arn': 'arn:aws:iam::123456789012:user/Alice',
'UserId': 'AKIAI44QH8DHBEXAMPLE'

Using Room persistence library, can I set my own primary key and manage it's "uniqueness" on my own?

I am using the Room library. One of my entities is coded like this:
#Entity
data class Authentication (
#PrimaryKey
#ColumnInfo(name = "system_id")
val systemID: String = "demo",
#ColumnInfo(name = "password")
val password: String? = "demo",
#ColumnInfo(name = "server_address")
val serverAddress: String? = "https://www.someSite.com/login/"
)
make the systemID the primary key. This is my Dao:
#Dao
interface AuthDao {
#Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertAuth(auth: Authentication): Long
#Query("SELECT * FROM authentication WHERE system_id = 1")
suspend fun getAuth(): Authentication?
#Update
suspend fun updateAuth(auth: Authentication): Int
#Delete
suspend fun deleteAuth(auth: Authentication)
}
I am managing the systemId's on the server. I know they will all be unique. However when I try to insert an object my code throws and exception stating that my primary key failed it's unique constraint. When I insert onConflict = OnConflictStrategy.REPLACE (as seen in the code above) everything works fine but before I placed that there my app crashed.
I checked the docs and didn't really find the answer to my question. I want to know why this error is thrown even when I KNOW I haven't tried to insert another object with the same systemID. Does Room not trust me? Is it because I didn't allow Room to autogenerate the primary key and thus Room and the compiler can't trust that I won't duplicate primary keys? Or am I missing something else?
Thanks in advance
EDIT
Perhaps I should have added this to my question. This is the code that has me confused.
fun checkForAuthenticationInDatabase() {
launch(IO){
var auth = AuthDatabase(getApplication()).authDao().getAuth()
if (auth == null){
Log.d("TAG", "auth was null")
auth = Authentication()
AuthDatabase(getApplication()).authDao().insertAuth(auth)
Log.d("TAG", auth.toString())
}
withContext(Main){
authentication.value = auth
}
}
}
As you can see, I first check for the existence of an object. If it doesn't exist and it comes back null, then I insert one. If it does exist, I just grab it. What I didn't catch before posting this question is that originally I was using int for the primary key (starting with 1 and no autogenerate). There is supposed to be only one row(record) in this database. Then I changed it to use the systemID as a primary key instead of an int but I forgot to change the query:
#Query("SELECT * FROM authentication WHERE system_id = 1")
suspend fun getAuth(): Authentication?
I realized my mistake and wanted to post this for others that may make the same mistake
even when I KNOW I haven't tried to insert another object with the same systemID
From your description of the error and that using REPLACE fixes the issue, then there is a row in the database that is the same system_id that you are trying to insert.
Notice that the description given is a little different to yours. SQLite, for which Room is basically a wrapper has no concept of storing objects, but of storing data in rows, each row containing the same number of elements (albeit that some may be null).
The difference between objects in an App and even if you equate a row in the database to an object (which it may represent and will in Room), is that in the database the data is persisted and remains in the database when the App is restarted. Perhaps it is this persistence that is confusing you.
If you change/use
#Query("SELECT * FROM authentication WHERE system_id = :system_id")
suspend fun getAuth(system_id: String): Authentication?
having #Query("SELECT * FROM authentication WHERE system_id = 1")
suspend fun getAuth(): Authentication? is prettymuch useless as it only allows you to extract 1 Authentication from the database, one which probably doesn't exist.
And use this prior to inserting, using the system_id, that you are inserting this will very likely confrim the case. That is that it will find the data and return a valid (non null) Authentication object .
Does Room not trust me?
To some extent yes, to some extent no.
Is it because I didn't allow Room to autogenerate the primary key and thus Room and the compiler can't trust that I won't duplicate primary keys?
No. Your code works fine and allows uniqueness when given.
Or am I missing something else?
As explained above, I believe that this is the case. Again with unique values for system_id the code works fine (this does assume that there are no other entities).
Consider the following which bar -
adding #Query("SELECT * FROM authentication")
fun getAllAuth(): List<Authentication> to AuthDao
removing suspend to allow running from the main thread (for convenience)
uses your code :-
val authDatabase = Room.databaseBuilder(this,AuthDatabase::class.java,"authdb")
.allowMainThreadQueries()
.build()
var a1 = Authentication("system_id1","password","www.server.etc")
var a2 = Authentication("system_id2","password","xxx.server.etc")
Log.d("AUTHINSERT","Insert of Authentication returned " + authDatabase.authDao().insertAuth(a1))
Log.d("AUTHINSERT","Insert of Authentication returned " + authDatabase.authDao().insertAuth(a2))
Log.d("AUTHINSERT","Insert of Authentication returned " + authDatabase.authDao().insertAuth(a1))
var authentications = authDatabase.authDao().getAllAuth()
for (authentication in authentications) {
Log.d("AUTHINFO",authentication.systemID)
}
Running this for the first time results in the log containing :-
2020-01-09 16:39:58.351 D/AUTHINSERT: Insert of Authentication returned 1
2020-01-09 16:39:58.352 D/AUTHINSERT: Insert of Authentication returned 2
2020-01-09 16:39:58.354 D/AUTHINSERT: Insert of Authentication returned 3
2020-01-09 16:39:58.358 D/AUTHINFO: system_id2
2020-01-09 16:39:58.358 D/AUTHINFO: system_id1
That is three rows appear to have been inserted, with rowid's 1-3.
rowid is a normally hidden row that has a unique integer (64bit signed) provided by SQLite sqlite (unless the rowid is aliased).
However, only 2 Authentication objects have been output. This is because the row with a rowid of 1 has been deleted and the row with a rowid of 3 has been added. That's what REPLACE does.
If the code above is run again then the result is :-
2020-01-09 16:44:25.455 D/AUTHINSERT: Insert of Authentication returned 4
2020-01-09 16:44:25.456 D/AUTHINSERT: Insert of Authentication returned 5
2020-01-09 16:44:25.458 D/AUTHINSERT: Insert of Authentication returned 6
2020-01-09 16:44:25.462 D/AUTHINFO: system_id2
2020-01-09 16:44:25.462 D/AUTHINFO: system_id1
That is the data in the database has been retained and because the data in the objects (albeit that they are not the same objects as the objects would have been garbage collected and deleted) is the same. The two rows have been deleted and new rows inserted (rowid's 5 and 6 will be in the database).

How to validate session ID if I know the session ID in Apache Shiro without the use of any hash maps?

I know that the session ID can be validated using hashmap and attaching it to a listener. Also there was a deprecated method to validate using only the session ID string.
I want to know is there an alternative way to validate the known session ID in Apache Shiro without the use of any hashmaps?
An alternate solution would be to create the subject using the passed session ID and then trying to get the session of that subject. If a session exist then it will return its session else null. For example, below method can be used to validate an Apache Shiro's session using a passed session ID.
public static boolean isSessionValid(String sessionId){
Subject requestedSubject = new Subject.Builder().sessionId(sessionId).buildSubject();
return !(requestedSubject.getSession(false) == null);
}

Transactional Create with Validation in ServiceStack Redis Client

User has DisplayName and it is unique for Users.
I want to Create User but firstly I have to check display name (DisplayName could not be duplicated for Users)
I've checked ServiceStack examples and I could not see Transactional Insert/Update with validation check.
How can I perform it. I dont want to write "Validation Tasks" for redis db.
I dont want inconsistency in db.
The ServiceStack.Redis client does have support for Redis's WATCH and transactions where these Redis commands:
WATCH mykey
test = EXIST mykey
MULTI
SET mykey $val
EXEC
Can be accomplished with:
var redis = new RedisClient();
redis.Watch("mykey");
if (!redis.ContainsKey("mykey")) return;
using (var trans = redis.CreateTransaction()) {
trans.QueueCommand(r => r.Set("mykey", "val"));
trans.Commit();
}
Is possible to perform redis transactions. More information here
WATCH mykey
test = EXIST mykey
MULTI
SET mykey $val
EXEC
Using PHP have um better example: here