How to use Spring Hatoas ControllerLinkBuilder for a Thymeleaf templated scheduled email - spring

I'm using Spring Hateoas in a Boot app to avoid manual creation of links in the view. It works great in Thymeleaf views, it works when a controller calls a service to send an email that is also rendered by Thymeleaf.
The code to create link is pretty standard
this.readLink = linkTo(methodOn(PostController.class)
.readPost(eventId, postId))
.withRel("ReadPost");
But for a #Scheduled service generated email, it fails like this
015-08-23 22:28:40.886 ERROR 1180 --- [pool-2-thread-1] o.s.s.s.TaskUtils$LoggingErrorHandler : Unexpected error occurred in scheduled task.
java.lang.IllegalStateException: Could not find current request via RequestContextHolder. Is this being called from a Spring MVC handler?
at org.springframework.util.Assert.state(Assert.java:392) ~[spring-core-4.2.0.RELEASE.jar:4.2.0.RELEASE]
at org.springframework.hateoas.mvc.ControllerLinkBuilder.getCurrentRequest(ControllerLinkBuilder.java:242) ~[spring-hateoas-0.18.0.RELEASE.jar:na]
at org.springframework.hateoas.mvc.ControllerLinkBuilder.getBuilder(ControllerLinkBuilder.java:189) ~[spring-hateoas-0.18.0.RELEASE.jar:na]
at org.springframework.hateoas.mvc.ControllerLinkBuilderFactory.linkTo(ControllerLinkBuilderFactory.java:121) ~[spring-hateoas-0.18.0.RELEASE.jar:na]
Is there anything I can do to get around the lack of an HttpServletRequest due to the code running as a #Scheduled job?

ControllerLinkBuilder currently can only be used from within a request as only that allows it to create a fully qualified link using server and port information from it.
Within an #Scheduled-invoked method that information is not available. If you provide more information on what you're actually creating in that very method, I can suggest workarounds.

Related

What can cause a LazyInitatializationException whereas Spring Open In View is enabled?

I am analysing a "classic" Hibernate error :
org.hibernate.LazyInitializationException : could not initialize proxy – no Session.
I am wondering how it could happen whereas the Spring Open In View mode is enabled?
If you have any documentation or knowledge on a possible reason, please share.
Thanks
Here are some feebacks on my context, and an example of what could cause LazyInitializationException event if Spring Open In View is enabled.
Context
My application is a REST API server developed with Spring Boot 2.5.3.
Spring Open In View is kept enabled by default.
A lot of Services are annotated with #Transactional methods.
Spring-data is used, and Entitymanager too, to create some native queries.
The error
One REST API request, that generates a lot requests to the database (both selections and insertions), fails with LazyInitializationException.
Debugging
By setting a breakpoint when LazyInitializationException is thrown, I discovered that the exception is thrown in org.hibernate.proxy.AbstractLazyInitializer#initialize, because the session is null. Then I discovered that the session is set to null, when the method EntityManager.clear is called. For any reason I don't know, this method was explicitely called in the code.
Fixing
So I just removed the call to EntityManager.clear, and the request works. I'm still wondering why previous developers wanted to clear the EntityManager, probably because they were confused with the transaction management.
Conclusion
Even in Spring Open In View is enabled, and as a result, event if a Hibernate Session is opened, calling EntityManager.clear unset the session to the entities loaded before. Then trying to access a Lazy Loaded field on those entities throws LazyInitializationException.
I hope this will help someone.
Here is the documentation from the latest hibernate version.
As you can see
Indicates an attempt to access not-yet-fetched data outside of a
session context. For example, when an uninitialized proxy or
collection is accessed after the session was closed.
Most probably somewhere you read some entity and then outside of a transaction you try to read some collection which was by default lazy loaded. So then another request needs to be done to database, but since you are out of transaction you receive this exception.
This usually occurs in case you load an entity without the annotation #Transactional or some other configuration to load it inside a transaction and then you give this to your controller to be returned to the user. Then the controller will use jackson or some other library to convert the entity object into a json and will try to read any field. At this point trying to read any lazy loaded collections from the entity, will result in this exception since the read will be outside of a transaction.

Error page registrar and Global exception handling

I am creating a Spring Boot web application, but i am confused why people use Global Exception handlers(#ControllerAdvice) when there is Error Page Registrar which is neater and more explicit. Please can someone explain more and is it possible to call an Error page registrar from a global Exception Handler Class( class annoted with #ControllerAdvice, with an #Exceptionhandler method).
As Brian answer, I think you can do this. I got a sample to prove this one in here if you still need to refer: https://github.com/kennytai/SampleSpringbootExceptionHandler
At this sample, I use the #ControllerAdvice in class GlobalExceptionHandler to manage all exceptions from TestController.
Hope this help.
It's actually the opposite the error pages mechanism in Spring Boot is the global one; it's catching all exceptions unhandled by the application. Note that in a Servlet environment, it's even dispatching the request back into the container on the /error path.
You're right though, this mechanism is really powerful and you can achieve a lot with it.
The other exception handling mechanisms you're mentioning are provided by Spring MVC itself. They're executed during the handling of the request and don't require an additional dispatch to the container. In some cases, they can be more limited because they offer less features than the full ErrorController (which is an MVC Controller).
But unlike error pages, you can configure those to focus on only specific errors:
You can declare an #ExceptionHandler within a Controller and specify the type of Exception you'd like to handle
You can configure the #ControllerAdvice annotation to only apply to specific packages, Controllers extending a specific interface or annotated with a specific annotation
I'd say the latter are quite useful when you want to deal with business exceptions at the controller level. You can do that with error pages, but you might end up with a single error controller dealing with too many things.

Spring mvc interceptor Basics

I am new to Spring and currently working on a spring application.
I am very confused regarding the spring interceptor and Interceptor in Spring security.
I have below doubts.
1. What is the use of Interceptor ? Is it used to modify the requested url or to validate the url ?
2. Is it possible that through interceptor i can modify my url /Test/MyTest to /Test/Intercept/MyTest ?
3. If Interceptor is only used to vaidate the url then only by url-pattern=/"somevalue" it will work or need to implement Interceptorhandler ?
Please help me out to understand these basic functionalities of interceptor.
I went through lot of sites but still not clear about all these concepts.
An interceptor is somewhat like a filter. A filter processes the request and response around a servlet and an interceptor processes the request and optionally the model around a spring controller. Common uses are pre-processing a request to ensure that a condition is realized (preHandle), or populating the model with attributes common to different controller methods (postHandle). afterCompletion is mainly used to perform cleanup at the end of request processing.
Actually interceptor can do three things
preHandle(…) – called just before the action
postHandle(…) – called immediately after the action
afterCompletion(…) – called just before sending response to view
Best example of prehandle is-checking whether the user is logged in or not.
Hope you have got some idea of interceptor
Spring MVC Interceptor is similar to Servlet Fiter Concept. Spring MVC provides ability to define set of classes called interceptor which will be called before and after a request being served. Interceptor will implement HandlerInterceptor which following thee methods need to be implemented:
preHandle() : Called before the handler execution
postHandle() : Called after the handler execution
afterCompletion() : Called after the complete request has finished
There is a good tutorial by MKYONG which I recommend you to have a look at it that I found it helpful in understanding the fundamental concept of interceptor. Hope that helps to get you started.

spring-security-redirect is not read by spring security 3.1?

So we're using spring-security-redirect as a parameter in the form that is sent to j_spring_security_check, in order to send the user to the correct page after a successful login. Migrating from Spring security 3.0 to 3.1, this stopped working. We use a subclass of SavedRequestAwareAuthenticationSuccessHandler, overriding onAuthenticationSuccess(), and debugging that method I see that getTargetUrlParameter() returns null. isAlwaysUseDefaultTargetUrl() returns false.
Browsing around I can't find anyone having similar problems... I find some references to AbstractAuthenticationTargetUrlRequestHandler.DEFAULT_TARGET_PARAMETER, which seems to have disappeared in 3.1.
Any ideas?
As per Spring security 3.1 xsd,
Attribute : authentication-success-handler-ref
Reference to an AuthenticationSuccessHandler bean which should be used to handle a successful authentication
request. Should not be used in combination with default-target-url (or always-use-default-target-url) as the
implementation should always deal with navigation to the subsequent destination.
So, in your subclass, you have to perform the redirection.

How to configure spring HandlerExceptionResolver to handle NullPointerException thrown in jsp?

From a jsp is thrown a NullPointerException for example using <% null.toString(); %>
This exception is not handled by the HandlerExceptionResolver, but thrown to the web container(tomcat) and converted into a code 500 error.
How can I configure spring to get that error in my HandlerExceptionResolver ?
Details:
Spring can be configured to handle exceptions thrown inside Controllers, but not exceptions thrown by view.
Of course i can resolve the NullPointerException, but i want to design a solution that will gracefully resolve any possible problem on the web application in order to display a user friendly message to the user.
See the HandlerInterceptor interface instead. You'll want the afterCompletion method. You can then intercept the response and then set the appropriate header information to redirect to a container-configured error web page. You're right that Spring doesn't have this functionality, this is going to have to be specified by the web.xml which determines which codes map to which pages.
I have not worked with this particular bit of the spring framework, but the docs say
"Interface to be implemented by objects than can resolve exceptions thrown during handler mapping or execution, in the typical case to error views. Implementors are typically registered as beans in the application context.
Error views are analogous to the error page JSPs, but can be used with any kind of exception including any checked exception, with potentially fine-granular mappings for specific handlers."
so I'd imagine that given that NullPointer extends RuntimeException the framework isn't designed to catch it. Is there a reason the exception(s) can't be handled in the controller directly?

Resources