Controlling hibernate exception message - java

Is there any way that Hibernate exception message could be controlled so that it doesn't include the placeholder data for the failed query.
e.g. for a failed insert query (lets say constraint violation), hibernate logs the exception with the input data. For privacy purpose, this needs to be removed from the logs.

I am not aware of any Hibernate configuration for this, but I would say that this is more suitable for logging configuration anyway.
For example, in log4j you could write custom appender/layout to intercept and replace the messages with the desired content.

Related

Is that Spring transaction is applied to normal(non DB) operations as well?

I have applied spring transaction on service layer of application. There is one method which performing following two operations
1) send message to SQS.
2) And logs that entry in DB.
So, while adding log in DB if any exception occurs then operation (1) will roll backed ? OR Spring will apply transaction on non DB operations ?
Rollback in case of exception is applied to anything that is managed by that transaction. Sending a message to the SQS is not managed by the database transaction, therefore it will not be rolledback.
To achieve this you would need to make a hook into the rollback and do the rollback equivalent of the sending the message to SQS.

Add custom value to every log message

Let's say that I have a REST API with endpoint /user/{user_id}/foo.
Now when it is called I would like that all logs that come from handling this request contain information about {user_id}. Is it possible to achieve that without passing {user_id} to every method?
I'm using SLF4j for logging, my application is based on Spring Boot.
You could also use MDC for this, see here. It's essentially a map, you just put your contextual information in it (e.g. user id) and then you can use it in your log layout. Be aware that this only works with certain underlying frameworks like logback, where a sample layout pattern would look like this:
<Pattern>%X{user_id} %m%n</Pattern>
Check the logback manual for more details on this.
You can use Logback's Mapped Diagnotic Context to propagate the {user_id} to every log message.
There are two parts to this:
Push your {user_id} into MDC e.g. MDC.put("user_id", "Pawel");
Include the MDC entry in your log statements. You do this by specifying it in your logging pattern. So, if you store the user id in a MDC entry named "user_id" the you would set logging.pattern.level=user_id:%X{user_id} %5p to include the value of that entry in every log event.
More details in the docs

Keycloak exception "Cannot access delegate without a transaction"

Context: Keycloak 1.9.1.Final and newer versions
Hi,
I have created a custom user federation provider which is a simple variation of the Keycloak's classpath property federation provider example. Instead of reading the usernames in a property file, I fetch then from an external web service.
My trouble is that sometimes I get the following exception when trying to authenticate with a test user:
Failed authentication: java.lang.IllegalStateException: Cannot access delegate without a transaction
at org.keycloak.models.cache.infinispan.UserCacheSession.getDelegate(UserCacheSession.java:78)
at org.keycloak.models.cache.infinispan.UserCacheSession.addUser(UserCacheSession.java:442)
at com.example.keycloak.MyFederationProvider.getUserModel(MyFederationProvider.java:324)
at com.example.keycloak.MyFederationProvider.getUserByUsername(MyFederationProvider.java:206)
at org.keycloak.models.UserFederationManager.getUserByUsername(UserFederationManager.java:237)
at org.keycloak.models.utils.KeycloakModelUtils.findUserByNameOrEmail(KeycloakModelUtils.java:273)
at org.keycloak.authentication.authenticators.browser.AbstractUsernameFormAuthenticator.validateUserAndPassword(AbstractUsernameFormAuthenticator.java:127)
at org.keycloak.authentication.authenticators.browser.UsernamePasswordForm.validateForm(UsernamePasswordForm.java:56)
at org.keycloak.authentication.authenticators.browser.UsernamePasswordForm.action(UsernamePasswordForm.java:49)
at org.keycloak.authentication.DefaultAuthenticationFlow.processAction(DefaultAuthenticationFlow.java:84)
at org.keycloak.authentication.AuthenticationProcessor.authenticationAction(AuthenticationProcessor.java:759)
at org.keycloak.services.resources.LoginActionsService.processFlow(LoginActionsService.java:359)
at org.keycloak.services.resources.LoginActionsService.processAuthentication(LoginActionsService.java:341)
at org.keycloak.services.resources.LoginActionsService.authenticateForm(LoginActionsService.java:386)
...
I can't figure out why this exception occures. I looked at the org.keycloak.models.cache.infinispan.UserCacheSession class and I could see that the exception is thrown when transactionActive variable is false, but I don't understand under what conditions it is set to false.
I tried forcing a transaction with KeycloakModelUtils.runJobInTransaction() method or by adding begin() and commit() arround the addUser() call, but it didn't solved the issue (I got a new error which informs that transaction is already active).
Did you already experienced this exception and know how to avoid it ?
Thanks a lot
I think I could find my error (or at least a workarround).
The getInstance() method of my user federation provider was always returning the same object (a singleton). I updated it in order to make it create a new provider every time the method is called.
This seems to solve the issue.

Mixing JTA and JDBC transactions

I have a Java SE(!) scenario with JMS and JPA where I might need distributed transactions as well as "regular" JDBC transactions. I have to listen to a queue which sends service requests, persist log on receiving, process the request and update the log after the request has been processed. The message shall only be acknowledged if the request has been processed successfully.
The first idea was to only use JTA (provided by Bitronix). But there I face two problems:
no log will be persisted if the request can't be processed
the request won't be processed if the log can't be updated (unlikely but yet possible)
So the other idea is to create and update the log with regular JDBC transactions. Only the entitymanager(s) for the request transaction(s) would join the user transactions and the entity managers for creating and updating the log would commit directly.
Is it possible to "mix" JTA and JPA on a single persistence unit? Or do we already have patterns for those kinds of JMS and JDBC transactions?
I actually solved my problem with a slightly different approach. Instead of "mixing" JTA and JDBC transactions I used suspend and resume to work with different user transaction.
The task is still the same: I start a (JTA) user transaction that contains some JMS and JDBC transactions (receiving a message, performing some database operations). And in the middle of that workflow, I want to write a message log but that logging shall not be rolled back when the "outer" transaction fails.
So the solution is, in pseudo code:
transactionManager.begin()
doSomeJdbcStuff();
Transaction main = transactionManager.suspend();
// do the logging
transactionManager.begin() // <- now a new transaction is created and active!
doSomeLogging();
transactionManager.commit()
// continue
transactionManager.resume(main);
doSomeMoreJdbcStuff();
transactionManager.commit();

Restlet: Log Stack Trace for All 500 Errors

I'd like my Restlet application to log the stack trace for any Resource that generates a 500-series HTTP error (using the Context's Logger). As far as I can tell, this is not the default behavior.
In other words, I don't want my Resource classes to have any logger code at all in the represent and acceptRepresentation methods - they just throw a ResourceException. I want the logging logic to be handled in a centralized way across all Resource instances.
I can think of a couple of hackish ways of doing this (e.g., inherit from a Resource subclass that handles the logging logic), but it just seems like this is something that should be built-in to the framework.
What am I missing?
Take a look at StatusService:
Service to handle error statuses. If an exception is thrown within your application or Restlet code, it will be intercepted by this service if it is enabled. When an exception or an error is caught, the getStatus(Throwable, Request, Response) method is first invoked to obtain the status that you want to set on the response. [...]
I just discovered this last month and it allowed me to really compress a lot of my error handling code and also to ensure that exceptions were being handled, and being handled uniformly.
You might be able to use a filter to do this; in afterHandle() it could check the status code, and then try to log the exception. I'm not sure whether the exceptions are available to the filters though.

Categories

Resources