I faced with problem when error in JDBC transaction cause return JMS-message to queue, I guess so. It means that some message are being processed again.
My app has next configuration:
I have configured JtaTransactionManager like this:
...
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<tx:jta-transaction-manager/>
....
And I has configured JMS DefaultMessageListenerContainer like this:
#Bean
public DefaultMessageListenerContainer jmsContainer(ConnectionFactory connectionFactory, PlatformTransactionManager transactionManager, ....) throws NamingException {
DefaultMessageListenerContainer container = new DefaultMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.setSessionTransacted(true);
container.setTransactionManager(transactionManager);
....
return container;
}
In my case, when I receive a JMS message, in my code logic happens org.springframework.dao.DataIntegrityViolationException. I handle exception via try-catch block and I expect everything will be fine. But in this time, as I see, message return to queue and it being processed again. This behavior isn't reproduce, if in my code happens other Exception, like as IllegalStateException/RuntimeException.
And I suppose that error in JDBC transaction causes broke JMS transaction despite the fact I handle exception.
Let me know, is it correct that I use one transaction manager for JPA and JDBC?
Or I need two different implementations for my DataSource and JMS DefaultMessageListenerContainer?
Also, if I can produce more information, I will.
Thanks!
Related
Hey everyone!
For context I am working on a simple spring project in intelliJ to configure it with HotswapAgent using DCEVM [8u181 build 2 ] along with the compatible JDK [ 8u181 ] on the Payara 5.0 Application Server.
Please bear with me in the next few snippets of code and my plausible explanation of what's happening and this is not a question regarding Spring MVC syntax or it's working.
This is the sample code I am testing on Hotswapping [ Not the Inbuilt on JVM but using DCEVM ] and HotswapAgent[1.3.0]
HelloWorldController.java
#Controller
public class HelloWorldController {
#Autowired HelloService helloService;
#RequestMapping("/hello")
public String hello(
#RequestParam(value = "name", required = false, defaultValue = "World") String name,
Model model) {
model.addAttribute("name", name);
System.out.println( helloService.sayHello() );
return "helloworld";
}
I don't want to include the code for helloService as it might bloat this post.
HelloService.sayHello() just churns out the quintessential Hello World in the console
As you can see above that auto-wiring has been turned on and it does the proper function(said above).
After this I comment out the Autowired Annotation and the function call, and this gives me an error which is :
org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.annotation.AnnotationFormatError: java.lang.IllegalArgumentException: Wrong type at constant pool index
Focus on :
java.lang.IllegalArgumentException: Wrong type at constant pool index
I debugged the application and found out that the IllegalArgumentException was raised when AnnotationParser was parsing the annotations of the Spring Controller class from the Constant Pool and the members(of one of the annotation which is 'type' of the annotation) was not correct when it was taken from the Constant Pool of the Class.
So from my knowledge the hotdeploying is not being done correct ( even though HotswapAgent says it has reloaded the class on the Payara Server) or there is something wrong with the JVM communication or the JDK, and I say this because when I do the opposite that is comment out autowiring then hot deploy and then run, so then I get a null pointer exception.
Note: just for added information
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.NullPointerException
If anyone needs more information or code or logs on this then I'd be more than happy to clarify. Thank you for your time everyone.
The retention policy of the Autowire is #Retention(RetentionPolicy.RUNTIME).
According to the JVM specification , the annotation should be available in binary form. (Reference : https://docs.oracle.com/javase/specs/jls/se8/html/jls-9.html#jls-9.6.4.2)
My assumption is java keeps the reference in the constant pool of all the classes with RUNTIME annotation. When you hotswap it, the class is hot swapped but constant pool is not refrenshed to reflect the class swap.
There is an similar open issue with hotswapagent : https://github.com/HotswapProjects/HotswapAgent/issues/256
Well this was weird to solve but it's not related to JDK version or DCEVM, but to the dispatcher servlet of Spring.
My Dispatcher Servlet was missing:
<annotation-driven />
Which is why it couldn't register the controller class and caused unwanted behavior. Also missing was the added XML Schemas.
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"
Just for completion purposes or if would be of help to anyone, I'll post the complete dispatcher servlet configuration.
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<annotation-driven />
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<context:component-scan base-package="com.test" />
</beans:beans>
I'm trying to get a grip using MongoDB with the Spring Data MongoDB framework. I tried severeal approaches to connect to my local DB and insert + retrieve some collections and documents, using the official Spring Reference Documentation and some simple examples like this Hello-World-Demo.
Actually, for the beginning I'm going to use the MongoTemplate to keep it simple. But now I'run into the following problem.
When I use the Spring Configuration with annotations configure the setting needed to connect to my local DB, everything works fine.
Otherwise When I use XML for the configuration, I run into an java.lang.NullPointerException at com.mongodb.DBTCPConnector.getClusterDescription
Here are my configuration files and the example code for connecting to the DB:
Use Case 1 - Spring Configuration with annotations:
//package, imports etc. here
#Configuration
public class MongoConfiguration {
public #Bean MongoDbFactory mongoDbFactory() throws Exception {
return new SimpleMongoDbFactory(new MongoClient(), "Test1");
}
public #Bean MongoTemplate mongoTemplate() throws Exception {
return new MongoTemplate(mongoDbFactory());
}
}
Using the configuration class like this ...
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(MongoConfiguration.class);
MongoOperations mongoOperation = (MongoOperations) ctx.getBean("mongoTemplate");
ctx.close();
for (String s : mongoOperation.getCollectionNames()) {
System.out.println(s);
}
.. creates this output:
documents
leute
system.indexes
system.users
Use Case 2 - XML configuration (SpringConfig2.xml):
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
xsi:schemaLocation="http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/data/mongo
http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<mongo:mongo host="127.0.0.1" port="27017" />
<mongo:db-factory dbname="Test1" />
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
<constructor-arg name="mongoDbFactory" ref="mongoDbFactory" />
</bean>
</beans>
Using the configuration file like this ...
GenericXmlApplicationContext ctx = new GenericXmlApplicationContext("SpringConfig2.xml");
MongoOperations mongoOperation = (MongoOperations) ctx.getBean("mongoTemplate");
ctx.close();
for (String s : mongoOperation.getCollectionNames()) {
System.out.println(s);
}
.. results in this error
java.lang.NullPointerException
at com.mongodb.DBTCPConnector.getClusterDescription(DBTCPConnector.java:404)
at com.mongodb.DBTCPConnector.getMaxBsonObjectSize(DBTCPConnector.java:653)
at com.mongodb.Mongo.getMaxBsonObjectSize(Mongo.java:641)
at com.mongodb.DBCollectionImpl.find(DBCollectionImpl.java:81)
at com.mongodb.DBCollectionImpl.find(DBCollectionImpl.java:66)
at com.mongodb.DB.getCollectionNames(DB.java:510)
at org.springframework.data.mongodb.core.MongoTemplate$13.doInDB(MongoTemplate.java:1501)
at org.springframework.data.mongodb.core.MongoTemplate$13.doInDB(MongoTemplate.java:1499)
at org.springframework.data.mongodb.core.MongoTemplate.execute(MongoTemplate.java:394)
at org.springframework.data.mongodb.core.MongoTemplate.getCollectionNames(MongoTemplate.java:1499)
at test.main(Test.java:28)
When debugging DBTCPConnector.getClusterDescription, it seems that in the second case the private class variable cluster is for some reason not instantiated, leading to the described error.
What I'd like to know is: am I doing anything wrong within my XML-configuration or when using this config / context? Why does using XML-configuration end in an error, while using annotation configuration just works fine?
Basically (in the end) I just "copy+paste"'d the code examples from the official references for Spring / Spring Data MongoDB.
I'd appreciate any help / suggestions :)
Thanks to the hint from Tushar Mishra in the comments I was able to track down the origin of the error and why it occurs in one case but not in the other.
I'll try to explain in short, maybe it'll save someone some research time (or remember me if I perhaps run into this or a similar error again).
When closing either the AnnotationConfigApplicationContext-object (UC1) or the AnnotationConfigApplicationContext-object (UC2) with ctx.close(), from somewhere
org.springframework.beans.factory.DisposableBean#destroy() is invoked. As far as I understood, within there used singleton beans get destroyed by invoking the destroy()-methods
of each of those beans.
In short: closing the XXApplicationContext-object also destroys the MongoFactoryBean and with it closes the connection to the MongoDB.
So using c**tx.close()** at the described position leads to using a MongoOperations-object on a closed connection at the next line, resulting in the described NullPointerException.
And for why the sample code with Annotations (UC1) runs fine, whereas the sample code configured with XML (UC2) just breaks with an NullPointerException:
In UC1, the org.springframework.beans.factory.DisposableBean#destroy()-call is interupted by some DisposableBeanMethodInterceptor, which tries to redirect to a dispose() method.
But there is no method implemented in MongoFactoryBean, so the Mongo-connection stays alive and can be used even after ctx.close() was invoked. I think the connection will get killed later by the garbage collector, leading to the same error.
I'm not sure what to make of this, yet. If I should implement a dispose()-method myself or something alike. But at least I figured out, why this code sample behave different, although supposed to do the same thing.
Maybe it helps someone. Thanks again, Tushar, for giving a hint to the right direction.
I am spawning a thread which will keep pulling the chunk of records from database and putting them into the queue. This thread will be started on the server load. I want this thread to be active all the time. If there are no records in the database I want it to wait and check again after some time. I was thinking of using spring task scheduler to schedule this but not sure if that is right because I only want my task to be started once. What will be the good way of implementing this in Spring ?
Also, i need to have a boundary check that if my thread goes down (because of any error or exception condition) it should be re-instantiated after some time.
I can do all this in java by using thread communication methods but just trying if there is something available in Spring or Java for such scenarios.
Any suggestions or pointer will help.
You can use the #Scheduled annotation to run jobs. First create a class with a method that is annotated with #Scheduled.
Class
public class GitHubJob {
#Scheduled(fixedDelay = 604800000)
public void perform() {
//do Something
}
}
Then register this class in your configuration files.
spring-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:task="http://www.springframework.org/schema/task"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<tx:annotation-driven/>
<task:annotation-driven scheduler="myScheduler"/>
<task:scheduler id="myScheduler" pool-size="10"/>
<bean id="gitHubJob" class="org.tothought.spring.jobs.GitHubJob"/>
</beans>
For more about scheduling visit the Spring Docs.
#Scheduled(fixedDelay=3600000)
private void refreshValues() {
[...]
}
That runs a task once every hour. It needs to be void and accept no arguments. If you use Spring's Java configuration you'll also need to add the annotation #EnableScheduling to one of your #Configuration classes.
You can try using Quartz scheduler. http://quartz-scheduler.org/
That will allow you to specify the duration of time between task executions. You can set a flag (boolean) that says if the class has run before to avoid duplicating code that you only want to run the 'first' time.
Spring has out-ot-the-box support for scheduling tasks. Here are for the docs for the latest 3.2.x version of spring but check the docs for the version you are using. Looks like it uses Quartz under the hood for scheduling tasks.
I think your requirement is just regular senario which quartz or spring scheduling framework supports very well. but you want to create a spececial approach to impl it. my suggestion is to keep it simple and stupid. spring scheudling will take advantage your worker thread by pooling instead of runing it all the time.
As of statistics, it 's easy to check worker class's log. if you want see the statistics in web console, you need to record worker's log in database. I am sure you could make it easily in normal way.
I'm trying to test a simple Aspect.
The app compiles and runs fine, BUT I do not get the Aspect executed. Or at least, I do not get the output the aspect should produce.
(my aim is to write an exception logger for any ex that occures in the app. but first this test aspect should run...)
Maybe someone who has more experience in aspects see's what I'm doing wrong?
package business;
public interface Customer {
void addCustomer();
}
import org.springframework.stereotype.Component;
#Component
public class CustomerImpl implements Customer {
public void addCustomer() {
System.out.println("addCustomer() is running ");
}
}
#RequestScoped #Named
//this is backing bean for jsf page
public class Service {
#Inject
Customer cust;
add() {
System.out.println("Service is running ");
cust.addCustomer();
}
}
#Aspect
public class AspectComp {
#Before("within(business..*)")
public void out() {
System.out.println("system out works!!");
}
}
Spring:
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
">
<context:annotation-config />
<context:component-scan base-package="business" />
<aop:aspectj-autoproxy />
</beans>
Output:
Service is running
addCustomer() is running
The Aspect statement is missing.
You are creating your Component with its constructor, and not getting it from Spring container! That's the problem, or you must use AspectJ's load-time weaver.
Just inject your component (CustomerImpl) in your service and then use the injected instance.
I remember having a similar problem once; Spring wasn't actually loading the proxy as it did not recognize the #Aspect annotation as being an annotation-scanable bean. I added the #Component annotation to the #Aspect notation and Spring started scanning it.
I never looked into the reasons why this happened, and why I needed to do that, so I cannot confirm that is the "proper" way of doing things. My gut would tell me that I had something missing in my config file; I can't imagine why Spring would not scan for #Aspect beans.
The other thing you can do, is to explicitly declare your Aspect bean in the XML config file as well to see if this the same type of problem you're having.
You can also enable debug logging in the Spring framework and see if your bean is being loaded by Spring. If not, then it gives you an idea where to start looking.
I'm looking for a way to have spring beans registering themselves to a job processor bean who in turn will execute the registered beans on a schedule.
I'm hoping that the bean would just have to implement an interface and by some spring mechanism get registered to the job processor bean. Or alternatively inject the job processor bean into the beans and then somehow the job processor bean can keep track of where it's been injected.
Any suggestions appreciated, it might be that spring is not the tool for this sort of thing?
Use a spring context something like this:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!--Scans the classpath for annotated
components #Component, #Repository,
#Service, and #Controller -->
<context:component-scan base-package="org.foo.bar"/>
<!--Activates #Required, #Autowired,
#PostConstruct, #PreDestroy
and #Resource-->
<context:annotation-config/>
</beans>
And define a pojo like this:
#Component
public class FooBar {}
And inject like this:
#Component
public class Baz {
#Autowired private FooBar fooBar;
}
Spring has a powerful abstraction layer for Task Execution and Scheduling.
In Spring 3, there are also some annotations that you can use to mark bean methods as scheduled (see Annotation Support for Scheduling and Asynchronous Execution)
You can let a method execute in a fixed interval:
#Scheduled(fixedRate=5000)
public void doSomething() {
// something that should execute periodically
}
Or you can add a CRON-style expression:
#Scheduled(cron="*/5 * * * * MON-FRI")
public void doSomething() {
// something that should execute on weekdays only
}
Here's the XML code you'll need to add (or something similar):
<task:annotation-driven executor="myExecutor" scheduler="myScheduler"/>
<task:executor id="myExecutor" pool-size="5"/>
<task:scheduler id="myScheduler" pool-size="10"/>
Used together with
<context:component-scan base-package="org.foo.bar"/>
<context:annotation-config/>
as described by PaulMcKenzie, that should get you where you want to go.