I have two classes to make asynchronus method call in java ee. I am following the link http://satishgopal.wordpress.com/2011/04/24/ejb-3-1-asynchronous-methods to learn how to do.
When I have invocate the asynrnous method , I am having following result.
Result:
INFO: caller method running in thread http-thread-pool-8083(5) date:1373866669346
INFO: start running asyncMethod in thread http-thread-pool-8083(5)
INFO: finished running asyncMethod in thread http-thread-pool-8083(5)
INFO: caller method running in thread http-thread-pool-8083(5) date:1373866672348
What I am expecting is not to wait asyncMethod() method invcation completed however as you can see from the result that asyncMethod() method invcation is not handled by another thread.
Using Glassfish 3.1.1 as Application container.
BusinessBean class
#ManagedBean
#Stateless
public class BusinessBean {
#Asynchronous
public void asyncMethod() {
System.out.println("start running asyncMethod in thread "+ Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("finished running asyncMethod in thread "+ Thread.currentThread().getName());
}
}
LoginBean class
#ManagedBean
#RequestScoped
public class LoginBean implements Serializable {
private static final long serialVersionUID = 1L;
#ManagedProperty(value="#{businessBean}")
BusinessBean businessBean;
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void login(){
System.out.println("caller method running in thread "+Thread.currentThread().getName()+" date:"+System.currentTimeMillis());
businessBean.asyncMethod();
System.out.println("caller method running in thread "+Thread.currentThread().getName()+" date:"+System.currentTimeMillis());
}
public BusinessBean getBusinessBean() {
return businessBean;
}
public void setBusinessBean(BusinessBean businessBean) {
this.businessBean = businessBean;
}
}
Get rid of the ManagedBean annotation for BusinessBean: it should be an Enterprise Java Bean, and it is thanks to the #Stateless annotation.
Also inject it by means of #EJB:
#EJB
private BusinessBean businessBean;
See this link for further reference.
Related
I just converted our application code into simple classes to express the problem concisely. Our use case contains a class which internally uses some helper classes with static methods which needs to be mocked. So, planned to use PowerMockito. No issues with this part, however we have one class where we have an anonymous block inside one of the methods. When we try to create an instance of this class, PowerMockito fails with a very vague error. Tried spending few hours to resolve the issue without any luck.
public abstract class AbstractClass {
public abstract void methodOne(String arg);
public void methodTwo()
{
System.out.println("In method two");
}
}
public class StaticMethod {
public static String someStaticMethod()
{
System.out.println("in static method");
return "static";
}
}
public class AbstractClassCaller {
public AbstractClassCaller()
{
StaticMethod.someStaticMethod();
// The following piece of code is the problematic block
AbstractClass abstractClassInstance = new AbstractClass(){
public void methodOne(String methodArg)
{
System.out.println("In Method One");
}
};
}
}
#Test
#PrepareForTest({AbstractClassCaller.class,StaticMethod.class})
public class AbstractClassCallerTest {
#Test
public void test() throws Exception
{
PowerMockito.mockStatic(StaticMethod.class);
PowerMockito.when(StaticMethod.someStaticMethod()).thenReturn(
"PowerStatic");
// This is the code which triggers the exception
AbstractClassCaller instance = new AbstractClassCaller();
}
#ObjectFactory
public IObjectFactory getObjectFactory() {
return new org.powermock.modules.testng.PowerMockObjectFactory();
}
}
The above junit class fails with the following exception:
org.powermock.reflect.exceptions.ConstructorNotFoundException: Failed to lookup constructor with parameter types [ com.oracle.oal.seaas.AbstractClassCaller ] in class com.oracle.oal.seaas.AbstractClassCaller$1.
at com.oracle.oal.seaas.AbstractClassCallerTest.test(AbstractClassCallerTest.java:21)
Caused by: java.lang.NoSuchMethodException: com.oracle.oal.seaas.AbstractClassCaller$1.<init>(com.oracle.oal.seaas.AbstractClassCaller)
at com.oracle.oal.seaas.AbstractClassCallerTest.test(AbstractClassCallerTest.java:21)
// the following anonymous block in AbstractClassCaller is causing the issue:
AbstractClass abstractClassInstance = new AbstractClass(){
public void methodOne(String methodArg)
{
System.out.println("In Method One");
}
};
Any ideas on how to fix this issue?
I'm using custom crudrespository to persist data in redis. However, I'm unable to autowire custom repository.
All the configuration seems correct and redis is running on my local.
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
#Repository
public interface CustomRepository extends CrudRepository<String,
Long> {
String get(String key);
void put(String key, String value);
}
//////////
public class StorageServiceImpl implements IStorageService {
#Autowired
private CustomRepository respository;
#Override
public void saveParameter() {
this.respository.put("key1","value1");
}
#Override
public String getParameter() {
return this.respository.get("key1");
}
/////
#Service
public interface IStorageService {
void saveParameter();
String getParameter();
}
///////
#SpringBootApplication(scanBasePackages = {"com.example.cache"})
#EnableRedisRepositories(basePackages = {"com.example.cache.repository"})
public class ApplicationConfiguration {
public static void main(String[] args){
SpringApplication.run(ApplicationConfiguration.class, args);
new StorageServiceImpl().saveParameter();
System.out.println(new StorageServiceImpl().getParameter());
}
}
When I try running this application using gradle bootRun, I get
Exception in thread "main" java.lang.NullPointerException
at com.example.cache.impl.StorageServiceImpl.saveParameter(StorageServiceImpl.java:16)
at com.example.cache.ApplicationConfiguration.main(ApplicationConfiguration.java:17)
Not sure what's wrong?
You can't use new on any bean, you need to #Autowire it. The annotations only work with spring managed beans at every level.
Add a new bean with a a storage service and a method that makes your call after it is created.
Also, I can't remember if the spring-boot creates the bean if there is only one implementation but I believe your StorageServiceImpl needs the #Service annotation, not the interface.
Delete this from your ApplicationConfiguration class.
new StorageServiceImpl().saveParameter();
System.out.println(new StorageServiceImpl().getParameter());
Then add this new class.
#Service
public class Startup {
#Autowired
IStorageService storageService;
#PostConstruct
public void init(){
storageService.saveParameter();
System.out.println(storageService().getParameter());
}
}
And you need a config
#Configuration
#EnableRedisRepositories
public class ApplicationConfig {
#Bean
public RedisConnectionFactory connectionFactory() {
return new JedisConnectionFactory();
}
#Bean
public RedisTemplate<?, ?> redisTemplate() {
RedisTemplate<byte[], byte[]> template = new RedisTemplate<byte[], byte[]>();
return template;
}
}
Currently I am trying to get my script to run on a tomcat server by using the basic web container guidelines for spring-batch-boot from the documentation https://docs.spring.io/spring-batch/reference/html/configureJob.html
The script was working correctly as a jar file before modifications to the main class but when I try converting it to a servlet I am having issues with my #PostConstruct starting only on server startup. This code sets application.properties to spring.batch.job.enabled=false and has a controller of
#Controller
public class JobLauncherController {
#Autowired
JobLauncher jobLauncher;
#Autowired
Job job;
#RequestMapping("/jobLauncher.html")
public void handle() throws Exception{
jobLauncher.run(job, new JobParameters());
}
With The main Application to start the servlet for tomcat as
#SpringBootApplication
#EnableBatchProcessing
public class BatchApplication extends SpringBootServletInitializer{
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(BatchApplication.class);
}
public static void main(String[] args) {
SpringApplication.run(BatchApplication.class, args);
}
The problem is that my job uses custom item readers and writers that initializes it before running it using #PostConstruct. It runs the #PostConstruct at server startup which is what helps initialize the beans for writing.
My item readers/writers look like this
public class CustomReader extends ItemStreamSupport implements ItemReader<Acct>, ResourceAwareItemReaderItemStream<Acct> {
//basic autowiring
private int nextAcctIndex;
private List<Acct> acctsList = new ArrayList();
#PostConstruct
private void initialize() throws IOException {
//logic to parse files
acctsList = Collections.unmodifiableList(acctsList);
nextAcctIndex = 0;
}
#Override
public Acct read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException {
// System.out.println("Start Read");
Acct nextAcct = null;
if (nextAcctIndex < acctsList.size()) {
nextAcct = acctsList.get(nextAcctIndex);
nextAcctIndex++;
//System.out.println(nextAcct);
}
The BatchConfiguration calls everything like most examples as
#Bean public
IteamReader<Acct> CustomReader(){ return new CustomReader();}
My question is am I going about this the wrong way or is there a way to make it so the #PostConstruct is able to be called only when the Controller request for it?
you need to use
#BeforeStep
public void beforeStep(StepExecution stepExecution) {
init();
}
#PostConstruct is used to initialize once after applicationContext is loaded.
In your case you want to run this initialization every time job is running (you don't want data to be leaked across different jobs, right?)
I am using asp.net mvc applicaiton and I am new about cross cutting concers. So I need to know where can I use my logger code following example.
I have an interface that logs erros. I am implementing this interface on my code.
public interface ILogger { void Log(Exception exception); }
So I have Controller, ProductService, ProductRepository classes.
public interface ProductController: ApiController{
public IHttpActionResult Get(){
try {
productService.GetProducts();
}catch(Exception e){
logger.Log(e); // 1-Should I use logging in here?
}
}
}
Product service;
public class ProductService{
public IEnumerable<Product> GetProducts(){
try {
productRepository.GetAll();
}catch(Exception e){
logger.Log(e); // 2-Should I use logging in here?
}
}
}
In repository.
public class ProductRepository{
public IEnumerable<Product> GetAll(){
try {
}catch(Exception e){
logger.Log(e); // 3-Should I use logging in here?
}
}
}
I could not determine where can I use logging code. Or add logging in everywhere.
You can implement custom exception filter.
public class LogExceptionAttribute : ExceptionFilterAttribute
{
public ILogger logger { get; set; }
public LogExceptionAttribute(ILogger logger)
{
this.logger = logger;
}
public override void OnException(HttpActionExecutedContext actionExecutedContext)
{
var exception = actionExecutedContext.Exception;
logger.Log(actionExecutedContext.Exception);
// You could also send client a message about exception.
actionExecutedContext.Response =
actionExecutedContext.Request.CreateResponse(HttpStatusCode.InternalServerError, exception.Message);
}
}
Then register it on global level.
GlobalConfiguration.Configuration.Filters.Add(new LogExceptionAttribute(Logger));
This filter would be called for any unhandled exception thrown from controller method.
Working with spring, I am new to rabbitmq, i want to know where i am wrong.
I have written a rabbitmq connection factory, and a listener container containing a listener. I have also provided the listener container with an error handler but it doesnt seems to work.
My spring beans:
<rabbit:connection-factory id="RabbitMQConnectionFactory" virtual-host="${rabbitmq.vhost}" host="${rabbitmq.host}" port="${rabbitmq.port}" username="${rabbitmq.username}" password="${rabbitmq.password}"/>
<rabbit:listener-container missing-queues-fatal="false" declaration-retries="0" error-handler="errorHandlinginRabbitMQ" recovery-interval="10000" auto-startup="${rabbitmq.apc.autostartup}" max-concurrency="1" prefetch="1" concurrency="1" connection-factory="RabbitMQConnectionFactory" acknowledge="manual">
<rabbit:listener ref="apcRabbitMQListener" queue-names="${queue.tpg.rabbitmq.destination.apc}" exclusive="true" />
</rabbit:listener-container>
<bean id="errorHandlinginRabbitMQ" class="RabbitMQErrorHandler"/>
This is my RabbitMQErrorHandler class:
public class RabbitMQErrorHandler implements ErrorHandler
{
#Override
public void handleError(final Throwable exception)
{
System.out.println("error occurred in message listener and handled in error handler" + exception.toString());
}
}
What i assume is, if i provide invalid credentials to the connection factory, handleError method of the RabbitMQErrorHandler class should execute, and the server should start properly, however, when i try to run the server, the method does not executes(the exception is thrown in console) and the server is not able to start. Where am i missing something and what that might be?
The error handler is for handling errors during message delivery; since you haven't connected yet, there is no message for which to handle an error.
To get connection exceptions, you should implement ApplicationListener<ListenerContainerConsumerFailedEvent> and you will receive the failure as an event if you add it as a bean to the application context.
You will get other events (consumer started, consumer stopped etc) if you implement ApplicationListener<AmqpEvent>.
EDIT
<rabbit:listener-container auto-startup="false">
<rabbit:listener id="fooContainer" ref="foo" method="handleMessage"
queue-names="si.test.queue" />
</rabbit:listener-container>
<bean id="foo" class="com.example.Foo" />
Foo:
public class Foo {
public final CountDownLatch latch = new CountDownLatch(1);
public void handleMessage(String foo) {
System.out.println(foo);
this.latch.countDown();
}
}
App:
#SpringBootApplication
#ImportResource("context.xml")
public class So43208940Application implements CommandLineRunner {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(So43208940Application.class, args);
context.close();
}
#Autowired
private SimpleMessageListenerContainer fooContainer;
#Autowired
private CachingConnectionFactory connectionFactory;
#Autowired
private RabbitTemplate template;
#Autowired
private Foo foo;
#Override
public void run(String... args) throws Exception {
this.connectionFactory.setUsername("junk");
try {
this.fooContainer.start();
}
catch (Exception e) {
e.printStackTrace();
}
Thread.sleep(5000);
this.connectionFactory.setUsername("guest");
this.fooContainer.start();
System.out.println("Container started");
this.template.convertAndSend("si.test.queue", "foo");
foo.latch.await(10, TimeUnit.SECONDS);
}
}