Thread.setDefaultUncaughtExceptionHandler in Spring - java

I am developing a Spring application, and was wondering if there a part of the framework that let's me do something like this in a more elegant way, such as configuring something in XML?

If the purpose of your question is to set a custom UncaughtExceptionHandler through your application context, you can use:
<bean id="myhandler" class="java.lang.ThreadGroup">
<constructor-arg value="Test"/>
</bean>
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetClass" value="java.lang.Thread"/>
<property name="targetMethod" value="setDefaultUncaughtExceptionHandler"/>
<property name="arguments">
<list>
<ref bean="myhandler" />
</list>
</property>
</bean>
(N.B. replace myhandler with an Thread.UncaughtExceptionHandler of choice...)

You can also use #ControllerAdvice annotated classes for uncaught exception handling. Referencing from https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc, the following code will catch any Exception:
#ControllerAdvice
public class MyUncaughtExceptionHandler {
#ExceptionHandler(value = Exception.class)
public void defaultExceptionHandler(Exception e) {
// do whatever you want with the exception
}
}

Related

org.springframework.jdbc.cannotgetjdbcconnectionexception Rmi class loader disabled

Rather new to Java coming from a c# background.
What I am trying to achieve is just to expose a method to jConsole via jmx and rim.
When I run my service and open jConsole I can see the method there and all looks good, now the problem comes in when i try to run this method via the console. The error I get is "Problem invoking helloWorld : java.rmi.UnmarshalException: Error unmarshaling return; nested exception is: java.lang.ClassNotFoundException: org.springframework.jdbc.CannotGetJdbcConnectionException (no security manager: RMI class loader disabled)".
The method im trying to expose is
#ManagedOperation
public int helloWorld() throws Exception {
return jdbcTemplate.queryForInt(sql);
}
Here is my applicationContext file
<!-- this bean must not be lazily initialized if the exporting is to happen -->
<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter" lazy-init="false">
<property name="assembler" ref="assembler" />
<property name="namingStrategy" ref="namingStrategy" />
<property name="autodetect" value="true" />
</bean>
<bean id="jmxAttributeSource" class="org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource" />
<!-- will create management interface using annotation metadata -->
<bean id="assembler" class="org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler">
<property name="attributeSource" ref="jmxAttributeSource" />
</bean>
<!-- will pick up the ObjectName from the annotation -->
<bean id="namingStrategy" class="org.springframework.jmx.export.naming.MetadataNamingStrategy">
<property name="attributeSource" ref="jmxAttributeSource" />
</bean>
<context:component-scan base-package="com.bulks" />
<!-- enable annotations like #Autowired, which you also most likely need -->
<context:annotation-config/>
<bean class="com.bulksms.resources.HelloWorldResource"/>
<!-- setup basic datasource -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/apu"></property>
<property name="username" value="root"></property>
<property name="password" value="password"></property>
</bean>
<!-- jdbcTemplate bean -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
What am i missing so my method can be executed from the console?
-----SOLUTION------
So after hacking away at this for long i tried to put the sql part in its own method and then just call the method in the helloWorld method.... Low and behold!!!! SUCCESS!!!
public int helloWorld() throws Exception {
setValueFromQuery();
return value;
}
private void setValueFromQuery() {
this.value = jdbcTemplate.queryForInt(sql);
}
You exception is a nested exception, so its happened on on your application,
java.lang.ClassNotFoundException: org.springframework.jdbc.CannotGetJdbcConnectionException
So its say that there is a missing class, which could be the jdbc, make sure that you have it in your class path.
so if you have it, the check the connection criteria to your DB.

Can Controllers specify which Interceptors to use

I'm moving an existing spring (3.1.1) web mvc Controller (called LoginController) to using annotations, I had
<bean id="loginHandlerMapping"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="interceptors">
<list>
<ref bean="licenseInterceptor" />
<ref bean="propertyInterceptor" />
<ref bean="localeChangeInterceptor" />
</list>
</property>
<property name="urlMap">
<map>
<!-- used to include references to my LoginController -->
<entry key="error" value-ref="error" />
</map>
</property>
<property name="order">
<value>1</value>
</property>
</bean>
I changed my LoginController to be annotated. Some other classes had also been annotated previously so it will use the existing...
<bean id="requestMappingHandlerMapping"
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
<property name="interceptors">
<list>
<ref bean="licenseInterceptor" />
<ref bean="loginInterceptor" />
<ref bean="propertyInterceptor" />
</list>
</property>
</bean>
LoginController cannot use the loginInterceptor that others use however as it's a pre-login Controller but a post-login Interceptor.
What I want to know, is there a way to tell Spring that this specific Controller should NOT be used with a specific (loginInterceptor) Interceptor? And perhaps if it (and only it) could also use localeChangeInterceptor.
What have I tried
(works in Spring 3.2) Adding <mvc:interceptors> and their namespace to config but they don't seem to allow multiple bean references and exclude-mapping is Spring 3.2, I'm 3.1.1
Doing the processing in LoginInterceptor, handler is not of type LoginController - I can do ((HandlerMethod)handler).getBean() instanceof LoginController and that works but it's not pretty or flexible.
using the spring mvcnamespace you could do the following:
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<mvc:exclude-mapping path="/login"/>
<ref bean="loginInterceptor"/>
</mvc:interceptor>
<!-- .. further interceptors -->
</mvc:interceptors>
this allows to add paths that should not be intercepted by a specific interceptor.
add the mvc namespaces to your configuration root element..
xmlns:mvc="http://www.springframework.org/schema/mvc"
... and the schema ...
xsi:schemaLocation=" .....
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
...."
I've done this in the past by implementing it in the preHandle method in a HandlerInterceptorAdapter.
#Override
public final boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
// inspect handler object to see if it's LoginController
}
Here is what it took to get this working in the LoginController. A little like the solution of #blank but with some other nonsence, I'd still like to have a spring (annotation or config) way of fixing this though
public final boolean preHandle(HttpServletRequest request)
{
if (handler instanceof HandlerMethod &&
((HandlerMethod)handler).getBean() instanceof LoginController)
{
return true;
}
...
}

Manual configuration equivalent to mvc:annotation-driven [duplicate]

This question already has answers here:
Howto get rid of <mvc:annotation-driven />?
(4 answers)
Closed 9 years ago.
What exactly would be an equivalent manual configuration to mvc:annotation-driven in spring mvc? Because my webapp implements RequestMappingHandlerMapping, I cannot use mvc:annotation-driven but have to configure this myself.
Specifically I'm wondering what configuration has to be included in order for the #Async annotation to work. I am not sure if it does atm. I'm starting a background task at startup which is supposed to run as long as the webapp is running and it seems to me that the whole server waits for this (never-ending) method to finish. The #Async-Method is in a worker-service which gets called by another service on #PostConstruct.
Here are the two classes:
#Service
public class ModuleDirectoryWatcher{
#Autowired
ModuleDirectoryWatcherWorker worker;
#PostConstruct
public void startWatching() {
worker.startWatching();
}
}
#Service
public class ModuleDirectoryWatcherWorker {
#Async
public void startWatching() {
createPluginDir();
initializeClassloader();
initializeWatcher();
watch();
}
}
The relevant part of my applicationContext.xml looks like this so far:
<bean name="handlerAdapter"
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"</bean>
<bean class="org.springframework.http.converter.StringHttpMessageConverter"></bean>
<bean class="org.springframework.http.converter.ResourceHttpMessageConverter"></bean>
<bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter"></bean>
<bean class="org.springframework.http.converter.xml.XmlAwareFormHttpMessageConverter"></bean>
<bean class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter"></bean>
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>
</list>
</property>
</bean>
<bean name="handlerMapping"
class="com.coderunner.caliope.module.api.impl.ModuleHandlerMapping">
</bean>
Now I feel silly... In order to work, #Async and #Scheduled need
<task:annotation-driven executor="myExecutor" scheduler="myScheduler" />
<task:executor id="myExecutor" pool-size="5" />
<task:scheduler id="myScheduler" pool-size="10" />
even if you don't use
Maybe it helps someone out there

Is it possible to create a collections with Spring configuration?

Suppose I have a class MyClass which can be instantiated either with String or it have predefined static instances inside a class.
Something like this:
public class MyClass {
public final static MyClass A = new MyClass("A");
public final static MyClass B = new MyClass("B");
public final static MyClass C = new MyClass("C");
...
public MyClass(String name) {
...
}
}
Is it possible to create an ArrayList<MyClass> bean in Spring config somehow? Something like
<bean id="sequence" class="...ArrayList">
<member class="...MyClass" value="A"/>
<member ... />
....
</bean>
UPDATE 1
Is it possible to write following way:
<bean id="sequence" class="...ArrayList">
<constructor-arg>
<list>
<bean class="...MyClass" constructor-arg="A"/>
<bean class="...MyClass" constructor-arg="B"/>
<bean class="...MyClass" constructor-arg="C"/>
</list>
</constructor-arg>
</bean>
You should have a look at the Collections section in the spring IOC documentation.
<bean id="moreComplexObject" class="example.ComplexObject">
<property name="someList">
<list>
<value>a list element followed by a reference</value>
<ref bean="myDataSource" />
</list>
</property>
</bean>
You could do:
<bean id="myClassA" class="org.foo.MyClass">
<constructor-arg>
<bean class="java.lang.String">
<constructor-arg value="A"/>
</bean>
<constructor-arg>
</bean>
<bean id="sequence" class="java.util.ArrayList">
<constructor-arg>
<list>
<ref bean="myClassA" />
...
</list>
</constructor-arg>
</bean>
Note, however, that the most common approach is to inject a list directly into a bean rather than wrapping a list within a list first.
Yes. You can even create it as a standalone bean. See this thread for two examples.

How do I pass data to a method being run as a MethodInvokingJobDetailFactoryBean?

What I'm really trying to do is create a Quartz job that doesn't run concurrently, but also can access the JobExecutionContext in order to get the previousFireTime. Here's my object:
// imports...
public class UtilityObject {
private SomeService someService;
#Autowired
public UtilityObject(SomeService someService) {
this.someService = someService;
}
public void execute(JobExecutionContext ctx) throws JobExecutionException {
Date prevDate = ctx.getPreviousFireTime();
// rest of the code...
}
}
And here's how I've configured my bean:
<bean name="utilityBean" class="UtilityObject" />
<bean id="utilityJob"
class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetOjbect" ref="utilityBean" />
<property name="targetMethod" value="execute" />
<property name="concurrent" value="false" />
</bean>
<bean name="utilityTrigger"
class="org.springframework.scheduling.quartz.SimpleTriggerBean">
<property name="jobDetail" ref="utilityJob" />
<property name="startDelay" value="5000" />
<property name="repeatInterval" value="20000" />
</bean>
When I try to run this, it fails during the creation of the bean with
NoSuchMethodException: UtilityJob.execute()
Any ideas?
Solution:
After reading skaffman's answer, I was able to get my solution working. Using the trigger that I had, I knew that the name was, and figured out that the default group was 'DEFAULT'. I had my class extend the QuartzJobBean class, and then added this bit of code:
protected void executeInternal(JobExecutionContext ctx)
throws JobExecutionException {
boolean isRunning =
(ctx.getScheduler().getTriggerState("utilityTrigger", "DEFAULT") ==
Trigger.STATE_BLOCKED);
if (isRunning) {
// run the job
}
}
Sorry for the weird formatting; these are some long lines!
It is possible to pass arguments to MethodInvokingJobDetailFactoryBean in the same way as with a spring MethodInvokingFactoryBean using the arguments property.
For example:
<bean id="myJob"
class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="myBean" />
<property name="targetMethod" value="myMethod" />
<property name="arguments">
<list>
<value>greetings</value>
<ref bean="anotherBean"/>
</list>
</property>
</bean>
MethodInvokingJobDetailFactoryBean is handy, but primitive - it can only execute public methods with no arguments.
If your job needs access to the Quartz API, then you'll need to use JobDetailBean and QuartzJobBean instead of MethodInvokingJobDetailFactoryBean. See docs for instructions how. The QuartzJobBean is passed the current JobExecutionContext when it runs.

Categories