Tomee - slf4j create logs file but not writing on them - maven

I want to use log4j for my app (I don't need to handle the server logs for now). I searched for a solution but all post are related with server logs. When I run the app, the log4j.properties is read and the logs file are created but it didn't write on them.
I'm using Tomee as server. I have other project with Wildfly using the same solution for log4j and it works.
log4j.properties:
log4j.appender.TEST = org.apache.log4j.DailyRollingFileAppender
log4j.appender.TEST.File = /opt/share/test-project/logs/test.log
log4j.appender.TEST.DatePattern = '.'yyyy-MM-dd
log4j.appender.TEST.layout = org.apache.log4j.PatternLayout
log4j.appender.TEST.layout.ConversionPattern = [%d{ISO8601}] %5p - %x - %c.%M(%L): %m%n
# Define the types of logger and level of logging
#log4j.rootLogger.org = DEBUG,CONSOLE
log4j.logger.com.test=DEBUG, TEST
Log4jConfig class which is initialized:
import java.io.File;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.log4j.PropertyConfigurator;
#WebListener
public class Log4jConfig implements ServletContextListener {
private final static String LO4G_FILENAME="/opt/share/test-project/config/log4j.properties";
private static final Logger LOGGER = LoggerFactory.getLogger(Log4jConfig.class);
...
...
public void contextInitialized(ServletContextEvent arg0)
{
try{
File file = new File(LO4G_FILENAME);
if (file.exists())
{
PropertyConfigurator.configure(LO4G_FILENAME);
LOGGER.info("[Log4JInitServlet - contextInitialized] - Log4J configured:"+LO4G_FILENAME);
}
}catch (Exception e) {
LOGGER.error("[Log4JInitServlet - contextInitialized] - Exception >>",e);
}
}
}
Test.java:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.Gson;
#Path("/test")
public class TestWs {
private static final Logger LOGGER = LoggerFactory.getLogger(TestWs.class.getName());
//here LOGGER is null. If I put it into test() is not null but not write on the log either.
#GET
#Path("/")
#Produces(MediaType.APPLICATION_JSON)
public Response test(){
LOGGER.debug("[TestWs - init] - init");
long currentSystemTime = System.currentTimeMillis();
LOGGER.error("[TestWs - test] - Error: TEST");
LOGGER.debug("[TestWs - test] - Finish Timing:"+(System.currentTimeMillis()-currentSystemTime));
return Response.ok().build();
}
}
POM.xml:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.12</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
<version>1.7.12</version>
</dependency>
Any idea?

upgrade dependency of slf4f :
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.22</version>
</dependency>
use private static final Logger logger = LoggerFactory.getLogger(class-name.class); into class in which you want to create logs.
use bellow log4j configuration :-
Root logger option
log4j.rootLogger=INFO, file
Direct log messages to a log file
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./logs/log.log
log4j.appender.file.MaxFileSize=10MB
log4j.appender.file.MaxBackupIndex=10
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
log4j.logger.org.springframework=WARN
log4j.logger.com.amstech=DEBUG

I'm not sure of all the setup but if you put log4j lib/config in the container you can need to set in conf/system.properties:
openejb.logger.external=true
otherwise (for legacy reasons), tomee will setup log4j in a custom way making your configuration not respected. This property just means "use normal log4j behavior".

Related

Spring Data JDBC + Querydsl: error "JdbcRepositoryFactory does not support Querydsl"

I want to use Spring Data JDBC with QueryDSL support. According to Spring documentation (https://docs.spring.io/spring-data/jdbc/docs/current/reference/html/#core.extensions.querydsl) it is supported, but I couldn't make it working.
I use MariaDB as database and my version of SpringBoot is 2.6.0.
My dependencies in pom.xml:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-sql-spring</artifactId>
</dependency>
Configuration:
#Configuration
#EnableJdbcRepositories
#EnableTransactionManagement
public class DBConfig {
}
My entity class:
package com.test.model.metadata;
import org.springframework.data.annotation.Id;
import org.springframework.data.relational.core.mapping.Table;
#Table
public class Action {
#Id
private long id;
private String name;
...
}
My repository class:
package com.test.repository;
import java.util.List;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.stereotype.Repository;
import com.test.model.Action;
import com.querydsl.core.types.Predicate;
#Repository
public interface ActionRepository extends PagingAndSortingRepository<Action, Long>, QuerydslPredicateExecutor<Action> {
#Override
List<Action> findAll(Predicate predicate);
}
QueryDSL predicate usage:
QAction action = QAction.action;
Predicate predicate = action.name.like("%Accept%");
List<Action> actions = actionRepository.findAll(predicate);
Q-classes are generated properly by preprocessor, compilation suceeds but during application startup I am getting error:
org.springframework.data.repository.core.support.UnsupportedFragmentException: Repository com.atende.db.metadata.jdbcrepository.ActionRepository implements org.springframework.data.querydsl.QuerydslPredicateExecutor but JdbcRepositoryFactory does not support Querydsl!
What yet could be missing in my solution?
When I am using QueryDSL directly with JdbcTemplate it works:
QAction action = QAction.action;
SQLTemplates dialect = new MySQLTemplates();
Connection connection = DataSourceUtils.getConnection(jdbcTemplate.getDataSource());
SQLQuery<String> query = new SQLQuery<>(connection, dialect);
List<Tuple> actions = query.select(action.id, action.name)
.from(action)
.where(action.name.like("%Action%"))
.fetch();
I also tried to use infobip querydsl library (https://github.com/infobip/infobip-spring-data-querydsl) but got the same error.
This is a misinterpretation of the documentation (not your fault, it is structured in an unfortunate way).
You are looking at the preface which describes the general way to work with Spring Data modules.
This does not indicate that the module at hand (JDBC in this case) supports all the features mentioned.
Spring Data JDBC does not provide Querydsl support.
That means that the #EnableJdbcRepositories which activates spring-data-jdbc repository implementation does not provide Querydsl support.
If you have infobip-spring-data-jdbc-querydsl-boot-starter on classpath and remove #EnableJdbcRepositories it should work.
QuerydslJdbcPredicateExecutor is the fragment implementation.

Spring Cucumber ActiveProfiles annotation not working with CucumberContext

I'm working on a project where we have a component which consists:
core
connector to external system 1
connector to external system 2
The connectors are mutually exlusive (if connector1 is active, connector2 is always inactive and vice versa). The core and a single connector are autowired on startup of the ApplicationContext. Which connector is instantiated is based on a value in the spring application properties.
We're writing integration tests using spring-cucumber (v6.2.2). For each external system, I want to run a set of cucumber tests. I've created 2 testsets using annotations on the cucumber scenario's which allows me to seperate the tests for connector1 and connector2.
The problem I'm having is that I need both testsets to run with a different spring profile, so I can use a different configuration. I can't find how to do this.
Current implementation (with a single profile):
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.3.4.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-java</artifactId>
<version>6.2.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-junit</artifactId>
<version>6.2.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-spring</artifactId>
<version>6.2.2</version>
<scope>test</scope>
</dependency>
CucumberConnector1IT.java
package omitted.for.company.rules;
import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;
import org.junit.runner.RunWith;
#RunWith(Cucumber.class)
#CucumberOptions(
features = { "classpath:feature/" },
glue = { "omitted.for.company.rules.cucumber.step" },
plugin = { "pretty", "json:target/cucumber-report/cucumber.json",
"html:target/cucumber-report/cucumber.html" },
tags = "#Connector1 and not #ignore" // tags make sure only applicable tests are run
)
public class CucumberConnector1IT {
}
CucumberConnector2IT.java
package omitted.for.company.rules;
import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;
import org.junit.runner.RunWith;
#RunWith(Cucumber.class)
#CucumberOptions(
features = { "classpath:feature/" },
glue = { "omitted.for.company.rules.cucumber.step" },
plugin = { "pretty", "json:target/cucumber-report/cucumber.json",
"html:target/cucumber-report/cucumber.html" },
tags = "#Connector2 and not #ignore" // tags make sure only applicable tests are run
)
public class CucumberConnector2IT {
}
StepInitializer.java
package omitted.for.company.rules.steps;
import io.cucumber.java.Before;
import io.cucumber.spring.CucumberContextConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.ActiveProfiles;
#SpringBootTest
#ActiveProfiles("test") // I can only get this to work if the #ActiveProfiles and #CucumberContextConfiguration annotations are on the same class
#CucumberContextConfiguration
public class StepInitializer {
// mock some beans to use in cucumber test
#MockBean
private EventProducer eventProducer;
#MockBean
private RestInterface restInterface;
#Before
public void setup() {
}
}
So far everything works. But what I need now is to put the #ActiveProfiles() annotation on a different class than the #CucumberContextConfiguration. If I can do this then I can annotate the correct step classes with the required profiles.
Problem is that I don't understand the spring annotations well enough to know which ones I can move and which ones I cannot. I found this example of exactly what I'm trying to do (spring-cucumber-profiles repo, notice the location of the #ActiveProfiles annotation here) . Unfortunately, it uses an older version of cucumber-spring (v5.6.0). That version doesn't yet have the #CucumberContextConfiguration annotation and does some magic with the spring context according to the documentation (Release notes of cucumber-spring). I tried to checkout the example repo and upgrade it to v6.2.2 but couldn't get it working with the new version.
If anyone spots what I'm doing wrong in my own examples, or has the possibility to get the example repo working with version 6.2.2 of cucumber-spring that would be much appreciated.
Thanks in advance! :)
I've solved the issue by separating the packages a bit, and creating separate StepInitializer classes for both testsets.
Current setup:
Test runner:
package omitted.for.company.rules;
import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;
import org.junit.runner.RunWith;
#RunWith(Cucumber.class)
#CucumberOptions(
features = { "classpath:feature/" },
extraGlue = { "omitted.for.company.rules.cucumber.step.common" }, // used extraGlue instead of glue
plugin = { "pretty", "json:target/cucumber-report/cucumber.json",
"html:target/cucumber-report/cucumber.html" },
tags = "#Connector1 and not #ignore" // tags make sure only applicable tests are run
)
public class CucumberConnector1IT {
}
Context Configuration:
package omitted.for.company.rules.steps;
import io.cucumber.java.Before;
import io.cucumber.spring.CucumberContextConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.ActiveProfiles;
#SpringBootTest
#ActiveProfiles({ "test", "test-connector1" })
#CucumberContextConfiguration
public class Connector1StepInitializer {
// mock some beans to use in cucumber test
#MockBean
private EventProducer eventProducer;
#MockBean
private RestInterface restInterface;
#Autowired
private ApplicationContext applicationContext;
#Autowired
private Environment environment;
#Before
public void setup() {
assertThat(applicationContext).isNotNull();
assertThat(environment.getActiveProfiles()).containsOnly("test","test-connector1");
}
}
Both connectors/test runners have their own runner class and their own ContextConfiguration class.
It's very important that the classes containing the #CucumberContextConfiguration annotation are not in the shared glue package (as provided in the extraGlue property in the #CucumberOptions annotation).
Package structure looks like this:
├───common
│ └───step // Contains shared steps. This path should be in the 'extraGlue' field of the runner classes
├───connector1
│ │ CucumberConnector1IT.java // Runner 1
│ └───step
│ Connector1Steps.java // Specific steps
│ Connector1StepInitializer.java // has #ActiveProfiles and #CucumberContextConfiguration annotations, use to mock beans
└───connector2
│ CucumberConnector1IT.java // Runner 2
└───step
Connector2Steps.java // Specific steps
Connector2StepInitializer.java // has #ActiveProfiles and #CucumberContextConfiguration annotations, use to mock beans
This way I can still use different spring profiles :).

Infinispan cache returning null object

Getting NullPointer exception while put the values into cache using cache.put() method.
Environment:
Jboss 7.2
Here is the sample code I've written to reproduce the issue.
Configuration form standalone.xml file:
`<cache-container name="sampleCache" default-cache="default">
<local-cache name="default"/>
</cache-container>`
Added dependencies in deploy descriptor file like
`<jboss-deployment-structure>
<deployment>
<dependencies>
<module name="org.infinispan.commons" />
<module name="org.infinispan" />
</dependencies>
</deployment>
</jboss-deployment-structure>`
Getting the cache object via #Resource from Java code
`import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import org.infinispan.Cache;
/**
* InfiniSpanJbossCache Implementation
*
*/
#Startup
#Singleton
public class InfiniSpanJbossCacheExample {
#Resource(lookup="java:/jboss/infinispan/cache/sampleCache/default")
private static Cache<String, String> cache;
#PostConstruct
public static void deploy(){
cache.put("test","inserted1element");
}
}`
While trying to insert some values into cache(cache.put("","")) I'm getting the error, Did I miss any configs????

WebDrivermanager is not opening the browser

I am not able to open both IE and Chrome browsers using WebDriverManager dependency when i run as Maven test. I see that no error is thrown in console and test execution is inprogress even after several minutes.
I have a println statement before the opening the browser which gets printed in the console. Can someone please help me on this?where am I going wrong ?
I am using Spring Test Suite 3.3.0(instead of Eclipse), Java 1.8, Chrome Version - 67.0.3396.99, IE version - 11.0.60
Dependency in pom.xml
<dependency>
<groupId>io.github.bonigarcia</groupId>
<artifactId>webdrivermanager</artifactId>
<version>2.2.3</version>
</dependency>
</dependencies>
Java Class code
import io.github.bonigarcia.wdm.WebDriverManager;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.ie.InternetExplorerDriver;
import org.testng.annotations.Test;
public class SampleTest {
WebDriver driver;
#Test(priority = 2)
public void TC01()
{
System.out.println("Inside TC1");
WebDriverManager.iedriver().setup();
driver = new InternetExplorerDriver();
driver.get("https://www.google.com/");
}
#Test(priority = 1)
public void TC02()
{
System.out.println("Inside TC2");
}
}
Console
You can find a running example of Internet Explorer and WebDriverManager here. Moreover, take a look to the required configuration in Internet Explorer according to the Selenium doc.

Ignore MongoDB socket connection on Spring Test

I am using mongo in my spring project, but I cant connect to mongo server. Anyone knows a way to ignore this bean when executing tests, because sometimes I dont have the mongo server up and I dont want that this build fail.
I really like to know if I can ignore it using SpringRunner.
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
#RunWith(SpringRunner.class)
#SpringBootTest(classes = { Application.class })
public class ApplicationTests {
#Test
public void contextLoads() {
}
}
Stacktrace:
Caused by: org.springframework.dao.DataAccessResourceFailureException:
Timed out after 30000 ms while waiting for a server that matches WritableServerSelector.
Client view of cluster state is {type=UNKNOWN, servers=[{address=localhost:27017, type=UNKNOWN, state=CONNECTING, exception={com.mongodb.MongoSocketException: localhost}, caused by {java.net.UnknownHostException: localhost}}]; nested exception is com.mongodb.MongoTimeoutException: Timed out after 30000 ms while waiting for a server that matches WritableServerSelector. Client view of cluster state is {type=UNKNOWN, servers=[{address=localhost:27017, type=UNKNOWN, state=CONNECTING, exception={com.mongodb.MongoSocketException: localhost}, caused by {java.net.UnknownHostException: localhost}}]
Spring components:
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-parent</artifactId>
<version>Dalston.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
PS I stopped the mongodb at localhost intentionally.
You can disable Spring Boot's auto configuration of MongoDB by adding the following annotation to your ApplicationTests class:
#EnableAutoConfiguration(exclude={MongoAutoConfiguration.class, MongoDataAutoConfiguration.class})
This will prevent Spring Boot from creating the MongoClient (assuming there are no other classes in your test context annotated with #EnableAutoConfiguration or #SpringBootApplication).
I solved using embedded mongodb.
Dependency (https://github.com/flapdoodle-oss/de.flapdoodle.embed.mongo):
<dependency>
<groupId>de.flapdoodle.embed</groupId>
<artifactId>de.flapdoodle.embed.mongo</artifactId>
<scope>test</scope>
</dependency>
I added specific configuration on application-test.yml (execute using spring.profile.active=test)
spring:
data:
mongodb:
database: dbtest
host: localhost
port: 27028
And the ApplicationTests.java
#RunWith(SpringRunner.class)
#SpringBootTest(classes = { Application.class })
public class ApplicationTests {
private static final String LOCALHOST = "127.0.0.1";
private static final String DB_NAME = "dbtest";
private static final int MONGO_TEST_PORT = 27028;
private static MongodProcess mongoProcess;
private static Mongo mongo;
#BeforeClass
public static void initializeDB() throws IOException {
MongodStarter starter = MongodStarter.getDefaultInstance();
IMongodConfig mongodConfig = new MongodConfigBuilder()
.version(Version.Main.V3_3)
.net(new Net(LOCALHOST, MONGO_TEST_PORT, Network.localhostIsIPv6()))
.build();
MongodExecutable mongodExecutable = null;
try {
mongodExecutable = starter.prepare(mongodConfig);
mongoProcess = mongodExecutable.start();
mongo = new MongoClient(LOCALHOST, MONGO_TEST_PORT);
mongo.getDB(DB_NAME);
} finally {
if (mongodExecutable != null)
mongodExecutable.stop();
}
}
#Test
public void contextLoads() {}
#AfterClass
public static void shutdownDB() throws InterruptedException {
if (mongo != null) mongo.close();
if (mongoProcess != null) mongoProcess.stop();
}
}

Resources