I am using all annotated version of springmvc and I have a class where I have scheduled a method to be run every 5 seconds. However, it doesnt seem to be firing.
I have created a package to be scanned when the app fires up and I have declared the class in the following way:
#Configuration
#ComponentScan("com.iautomation")
#EnableWebMvc
#EnableTransactionManagement
#PropertySource("classpath:application.properties")
public class WebAppConfig extends WebMvcConfigurerAdapter {
My class and cron:
#Component
public class DemoServiceBasicUsageCron {
//#Scheduled(cron="*/1 * * * * ?")
#Scheduled(fixedRate=5000)
public void demoServiceMethod()
{
System.out.println("\n\n\n\n");
System.out.println("Method executed at every 5 seconds. Current time is :: ");
System.out.println("\n\n\n\n");
}
}
The package is scanned when the app starts:
DEBUG DefaultListableBeanFactory:463 - Finished creating instance of bean 'demoServiceBasicUsageCron'
and another debug log:
DEBUG BeanNameUrlHandlerMapping:86 - Rejected bean name 'demoServiceBasicUsageCron': no URL paths identified
When I load the app in eclipse I dont see anything in the console.
You have to annotate your Configuration class with #EnableScheduling
Related
I have a test defined with:
#ComponentScan(basePackages = { ... })
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = { AppConfig.class })
#WebMvcTest(secure = false)
public class MyTest extends AbstractJUnit4SpringContextTests {
#Autowired SomeClass target;
#Test public void test() { Assert.assertTrue(target != null); } // MCVE
}
Here's my ContextConfiguration class:
#Configuration
public class AppConfig {
#Bean
#ConfigurationProperties(prefix = "datasource")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
#Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
#Bean
ServletWebServerFactory servletWebServerFactory() {
return new TomcatServletWebServerFactory();
}
}
This test works fine, but it wastes a lot of time in MVC initialization due to the #WebMvcTest annotation. This particular test does not require any MVC functionality. The annotation ended up in there as a result of trial-and-error, to get the #Autowired annotation to work correctly. But now I want to remove it.
So... I went ahead and removed the #WebMvcTest annotation. But then the test fails because apparently the #ComponentScan does not have any effect unless #WebMvcTest is present (which I now remember, is the reason I added it).
Here's the actual error message:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type '...' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
I tried adding #SpringBootTest but it made no difference.
If instead, I add #EnableAutoConfiguration, I get a different error:
java.lang.IllegalArgumentException: dataSource or dataSourceClassName or jdbcUrl is required.
What annotation am I missing?
EDIT:
Why removing WebMvcTest annotation from my test in SpringBoot application causes ComponentScan to fail?
Because you have not annotated the class in a way that Spring's IoC/Dependency injection can work correctly.
Now that the answer is clear, here are a couple of suggestions for you to try. They may or may not work depending upon how your project and dependencies etc are put together.
END EDIT:
This particular test does not require any MVC functionality.
You should consider using one of the more direct auto-configuration annotations for the your tests if you don't need all of MVC but do want auto configuration. For instance, it appears you are testing with some data system. Perhaps the #DataJpaTest or #JdbcTest annotations would provide a more streamlined approach. These will enable auto configuration (IoC and Dependency injection).
What annotation am I missing?
As written above, the annotation you are missing is #Configuration
This is counter intuitive here because this isn't a configuration class. But without an appropriate annotation that enables Dependency injection to occur, this is the only way to get this to work. Why?
From the docs:
public #interface ComponentScan
Configures component scanning directives for use with #Configuration classes.
So your choices are:
Use a different auto config annotation as suggested above
Add the #Configuration annotation
I have to implement two simples java projects ; the first is an EJB projectwho contains a simple service which implement a remote interface, and the second project is a java client which try to call this ejb project ,
so here is what I did until now :
Context context = new InitialContext(jndiProperties);
TestServiceRemote proxy = (TestServiceRemote) context
.lookup("java:global/testEJB/TestService!services.TestServiceRemote");
System.out.println(proxy.showHello());
and this my ejb service :
#Stateless
public class TestService implements TestServiceRemote {
public TestService() {
}
#Override
public String showHello() {
return "Hello";
}
}
finally this my Remote interface :
#Remote
public interface TestServiceRemote {
public String showHello();
}
I had deployed the EJB in WIldfly 9 , but when I launch the java client i get this error shown in console :
Exception in thread "main" javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file: java.naming.factory.initial
at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:662)
at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:313)
at javax.naming.InitialContext.getURLOrDefaultInitCtx(InitialContext.java:350)
at javax.naming.InitialContext.lookup(InitialContext.java:417)
at swing.testClient.main(testClient.java:22)
Can someone tell me what I had wrong in my code ?
The java: namespace is not available by default in Java. You can either package your main class as an application client JAR inside an EAR and run it using an application client container launcher, or you can configure the InitialContext to have access to the java: namespace as described in this blog post.
In our project I have modules scout.client, scout.server, scout.shared and backend.
Backend has no dependencies to scout.server and scout.shared, but scout.server has dependencies to backend.
Inside backend project I have all business logic and calling all outside services.
My problem is when I try to test scout services that use some service from backend.
Because scout provide some great tool for mocking beans, we defined our service inside backend as beans as :
BEANS.getBeanManager().registerClass(CarService.class);
BEANS.getBeanManager().registerClass(PartnerService.class);
Both, CarService.class and PartnerService.class are in backend.
When I try to write some tests and I add #BeanMock to service in test
#BeanMock
private IPartnerService partnerService;
I get mock, but then every return every function is null, even if I write
doReturn(PartnerBuilder.standardPartnerListWithOneElement()).when(this.partnerService)
.getPartners(any(Set.class));
If I debug in my test, before this test is called with debugger I can get :
partnerService.getPartners(...) -> return a list of person
what is right, but when class that is tested calles this service it return null.
I understand that this could be due to missing annotation on interface #ApplicationScoped. Without this there is no guarantee that only one bean is created, and when statement react on another copy of that bean...?
I could not add annotation on interface because backend has no dependencies to scout modules.
How could I handle this kind of cases?
Tested class is :
public class UtilityPartner {
/**
* Method return service bean for getting partners by ids.
*
* #return
*/
private static IPartnerService getPartnerService() {
return BEANS.get(IPartnerService.class);
}
public static String getPartnerName(final Long partnerId) {
if (partnerId == null) {
return "";
}
final List<Partner> partners =
(List<Partner>) getPartnerService().getPartners(Sets.newHashSet(partnerId));
if (partners == null || partners.isEmpty()) {
return "";
}
final Partner partner = partners.get(0);
return LookupUtil.createLookupDescription(partner.getId(), partner.getName());
}
}
test class is :
#RunWith(ServerTestRunner.class)
#RunWithSubject("anonymous")
#RunWithServerSession(ServerSession.class)
public class TestUtilityPartner {
#BeanMock
private IPartnerService partnerService;
#Before
public void init() {
doReturn(PartnerBuilder.standardPartnerListWithOneElement()).when(this.partnerService).getPartners(any(Set.class));
}
#Test
public void getPartnerName() {
final String name = UtilityPartner.getPartnerName(10L);
Assert.assertEquals("My name", name); // NAME IS ""
}
}
Using #BeanMock does not help here, because you are not using an application scoped service:
In the init method you are changing the local field partnerService. However, in your test you call UtilityPartner.getPartnerService, which is creating a new instance (with BEANS.get(IPartnerService.class)).
#BeanMock is more useful for convenience for mocking application scoped beans.
You can always register your beans manually as shown by Jmini. Please do not forget to unregister the bean again after the test!
We recommend using org.eclipse.scout.rt.testing.shared.TestingUtility.registerBean(BeanMetaData), which is automatically adding a testing order and removing #TunnelToServer annotations.
I think that you should register your mock instance in the Bean manager (See bean registration in the Scout Architecture Document). You should use a small order (-10 000 is recommended for tests), in order for your mock to win over the productive registration. The best approach is to use the TestingUtility class to register/unregister your mock. Do not forget to call the unregisterBean() method (in the method annotated with #After):
import java.util.Collections;
import org.eclipse.scout.rt.platform.BeanMetaData;
import org.eclipse.scout.rt.platform.IBean;
import org.eclipse.scout.rt.testing.shared.TestingUtility;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
public class TestUtilityPartner {
private IBean<?> beanRegistration;
#Before
public void init() {
partnerService = Mockito.mock(IPartnerService.class);
// Register the mock using the Bean meta information:
BeanMetaData beanData = new BeanMetaData(IPartnerService.class)
.withInitialInstance(partnerService)
.withApplicationScoped(true);
this.beanRegistration = TestingUtility.registerBean(beanData);
// Mockito behavior:
Mockito.doReturn(Collections.singletonList(new Partner(34L, "John Smith")))
.when(partnerService).getPartners(Mockito.any(Set.class));
}
#After
public void after() {
// Unregister the mocked services:
TestingUtility.unregisterBean(this.beanRegistration);
}
#Test
public void getPartnerName() {
String name = UtilityPartner.getPartnerName(10L);
Assert.assertEquals("10 - John Smith", name);
}
}
I am not sure what #BeanMock (org.eclipse.scout.rt.testing.platform.mock.BeanMock) is doing, but according to Judith Gull's answer it will not work:
Using #BeanMock does not help here, because you are not using an application scoped service:
In the init method you are changing the local field partnerService. However, in your test you call UtilityPartner.getPartnerService, which is creating a new instance (with BEANS.get(IPartnerService.class)).
#BeanMock is more useful for convenience for mocking application scoped beans.
I have to create a class that implements ServletContextListener to add an event during the initialization or the shutdown of Tomcat. However, the class has to be located in a jar file inside WEB-INF/lib. After doing some readings, I found out that this is not possible, and the alternative is to use ServletContainerInitializer. However, only onStartup() method is available.
Is there any other alternatives where I can also add an event during the shutdown or destruction of the web application?
I am using Tomcat 8 and Java 8 btw.
Let your ServletContainerInitializer programmatically add a ServletContextListener which in turn does the desired job in its contextDestroyed().
servletContext.addListener(YourServletContextListener.class);
Not sure how you tested your code. But this the ServletContextListener works fine for me on Tomcat 8.5.5. Just try this code, no need to put this to separate JAR file.
#WebListener
public class AppContextListener implements ServletContextListener{
Logger log = LoggerFactory.getLogger(AppContextListener.class);
#Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
}
#Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
log.info("### Context is destroyed ###");
}
}
I have 2 POJOs, in which one of them is an EJB and the other is a helper class.
//EJB Bean class
#Singleton
#LocalBean
#Startup
public class EJBBean{
#PostConstruct
public void init(){
HelperClass helper = new HelperClass();
helper.init();
}
}
//Helper class
public class HelperClass{
private static Log LOG = LogFactory.getLog("HelperClass");
private static Long currentTime = new Date().getTime();
public void init(){
//Some statements that use Log and do other Initialization
}
}
When I deploy this EJB jar I am getting an error
java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory
I have the commons-logging-1.1.1.jar in the classpath; also, I have configured it to use Log4J. As a standalone app that is without EJB meta-data it works fine. Am I missing some EJB config?
BTW I am pretty new to EJB. I am using GlassFish 3.1, Eclipse Helios as IDE and EJB3.1.
This could be because you put the commons-logging-1.1.1.jar into the wrong directory or because your server already provides server-wide library which consists of logging classes.
By the way - I remember a lot of strange 'NoClassDefFoundError' because of mixing commons-logging, log4j and slf4j (especially in mismatching versions).