Beautify your Java web application with Bootstrap

Bootstrap is one of the most popular front-end framework for developing responsive web design. It includes buttons, form inputs, links, columns, and tons of other pre-formatted page objects.

The mixt of Bootstrap and Spring MVC gives a powerfull toolbox to develop a web application running in both desktop and mobile devices.

   

This post presents a very concise and easy way to integrate Bootstrap to a Spring MVC web project.

Add bootstrap to your project dependency

You can add Bootstrap to your project by downloading a zip file from the project web site http://getbootstrap.com, then unzip the content and copy it to the webapp resources directory.
But it is more interesting to get it as project a maven dependency to your project. This is made possible by the client-side web libraries webjars

<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>bootstrap</artifactId>
    <version>3.2.0</version>
    <exclusions>
        <exclusion>
            <groupId>org.webjars</groupId>
            <artifactId>jquery</artifactId>
        </exclusion>
    </exclusions>
</dependency>

<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>jquery</artifactId>
    <version>2.1.1</version>
</dependency>

Bootstrap javascript components needs JQuery. That’s why Bootstrap has a dependency to JQuery.
In this post we made the choice to exclude Bootstrap version and to import 2.1.1 version of JQuery.
You can manage the version by defining a dependency management to the project pom.

Configure Spring

We need to add a resource handler for /webjars/** to associate it with classpath:/META-INF/resources/webjars/ located in the bootstrap-3.2.0.jar

@EnableWebMvc
@Configuration
@ComponentScan(basePackages = { "com.mycompany.myproject.web.controller" })
public class MvcConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
        registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
    }
.................
..............

}

Add a bootstrap reference to the web page.

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="initial-scale=1, maximum-scale=1">
    <link rel='stylesheet' href='webjars/bootstrap/3.2.0/css/bootstrap.min.css'>
</head>
<body>
    
    <!-- YOUR CODE HERE -->

<script type="text/javascript" src="webjars/bootstrap/3.2.0/js/bootstrap.min.js"></script>
<script type="text/javascript" src="webjars/jquery/2.1.1/jquery.min.js"></script>
</body>
</html>

Jboss config

JBoss has a specific library management and in some cases it can’t find files in webjars dependency.
This problem can be solved by unpackaging webjars jars using maven dependency plugin.

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <executions>
        <execution>
            <id>unpack</id>
            <phase>compile</phase>
            <goals>
                 <goal>unpack</goal>
            </goals>
            <configuration>
                 <artifactItems>
                      <artifactItem>
                          <groupId>org.webjars</groupId>
                          <artifactId>bootstrap</artifactId>
                          <overWrite>false</overWrite>
                          <outputDirectory>${project.build.directory}/classes</outputDirectory>
                          <excludes>**/maven/**, **/*.MF</excludes>
                      </artifactItem>
                 </artifactItems>
            </configuration>
        </execution>
    </executions>
</plugin>

Samples and components

You can find many samples and plugins for bootstrap that can gives you inspiration for your web application design.
I recommend those sites and projects:

The picture bellow presents a screenshot for a demo web application using bootstrap.
user-list

Posted in JEE, WEB | Tagged , , , , , , , , , , | Leave a comment

Spring MVC – Full java based config

Spring MCV is a very powerful and flexible framework for web application development.

It doesn’t just implement the MVC pattern, it allows you to develop Rest web services.

   

This post presents a web project sample with a full java configuration using Spring MVC 4 and Servlet 3 api. The code source is available in this link.

This project implements client side for the persistence sample presented in Spring-Data-JPA article

1 – Add project dependenciesimlmplements

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>4.0.1.RELEASE</version>
</dependency>
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>servlet-api</artifactId>
    <version>3.0.1</version>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-mapper-asl</artifactId>
    <version>1.9.13</version>
</dependency>

2 – Spring MVC config class

import org.springframework.context.annotation.*;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import org.springframework.web.servlet.config.annotation.*;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@EnableWebMvc
@Configuration
@ComponentScan(basePackages = { "com.mycompany.myproject.web.controller" })
public class MvcConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
    }

    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }

    @Bean
    public InternalResourceViewResolver jspViewResolver() {
        InternalResourceViewResolver bean = new InternalResourceViewResolver();
        bean.setPrefix("/WEB-INF/views/");
        bean.setSuffix(".jsp");
        return bean;
    }

    @Bean(name = "multipartResolver")
    public CommonsMultipartResolver getMultipartResolver() {
        return new CommonsMultipartResolver();
    }

    @Bean(name = "messageSource")
    public ReloadableResourceBundleMessageSource getMessageSource() {
        ReloadableResourceBundleMessageSource resource = new ReloadableResourceBundleMessageSource();
        resource.setBasename("classpath:messages");
        resource.setDefaultEncoding("UTF-8");
        return resource;
    }

}


3 – Webapp initializer

With servlet 3 API you can use a class to configure your web project instead of the classic web.xml file.
You have to check if your application server or your servlet container supports servlet 3 spec. For Tomcat you can have this information in this link:
tomcat.apache.org/whichversion

import javax.servlet.ServletContext;
import javax.servlet.ServletRegistration;

import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.filter.DelegatingFilterProxy;
import org.springframework.web.servlet.DispatcherServlet;

public class WebAppInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext container) {
        // Create the 'root' Spring application context
        AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
        rootContext.register(ServiceConfig.class, JPAConfig.class, SecurityConfig.class);

        // Manage the lifecycle of the root application context
        container.addListener(new ContextLoaderListener(rootContext));

        // Create the dispatcher servlet's Spring application context
        AnnotationConfigWebApplicationContext dispatcherServlet = new AnnotationConfigWebApplicationContext();
        dispatcherServlet.register(MvcConfig.class);
            
        // Register and map the dispatcher servlet
        ServletRegistration.Dynamic dispatcher = container.addServlet("dispatcher", new DispatcherServlet(dispatcherServlet));
        dispatcher.setLoadOnStartup(1);
        dispatcher.addMapping("/");
        
    }

 }


4 – Model class.

public class User {
 
    private Long id;

    private String firstName;

    private String familyName;

    private String email;

    // add extra attributes
    	
    // add getters and setters
	
}

5 – Add view as jsp page
We create a usersView.jsp page with code source bellow to display users list.

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>

<div class="col-sm-offset-1 col-sm-10">

    <legend>
        <spring:message code="table.user.title" />
    </legend>

    <div>
        <table id="dataTable" class="table table-striped table-bordered">
            <thead>
                <tr>
                    <th><spring:message code="table.user.id" /></th>
                    <th><spring:message code="table.user.firstName" /></th>
                    <th><spring:message code="table.user.falilyName" /></th>
                    <th><spring:message code="table.user.email" /></th>
                </tr>
            <thead>
            <tbody>
                <c:forEach var="u" items="${usersModel}">
                    <tr>
                        <td>${u.id}</td>
                        <td>${u.firstName}</td>
                        <td>${u.familyName}</td>
                        <td>${u.email}</td>
                    <tr>
                </c:forEach>
            </tbody>
        </table>
    </div>
</div>

6 – Develop your controller

The @Controller annotation indicates that a particular class serves the role of a controller.
The @RequestMapping annotation is used to map a URL to either an entire class or a particular handler method.

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

@Controller
public class UserController {

    @Autowired
    private UserService userService;
 
    /**
    * Request mapping for user
    */
    @RequestMapping(value = "users", method = RequestMethod.GET)
    public ModelAndView getUsersView() {
        ModelAndView mv= new ModelAndView("usersView");
        mv.addObject("usersModel", userService.findAll());
        return mv;
    }
    
    /**
    * Rest web service
    */
    @RequestMapping(value = "/usersList", method = RequestMethod.GET)
    public @ResponseBody List<UserDto> getUsersRest() {
        return userService.findAll();
    }
}

7 – Test web project
When building your project you may have maven error telling you that the web.xml file is missing.
You can fix it by configuring the maven war plugin as presented bellow.

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-war-plugin</artifactId>
    <configuration>
        <failOnMissingWebXml>false</failOnMissingWebXml>
    </configuration>
</plugin>

  • Test display users

    http://localhost:8080/myproject/users

    spring_mvc_test

  • Test rest web service

    http://localhost:8080/myproject/usersList

    You will get json reponse.

    [
        {
            "id": 1,
            "firstName": "adminName",
            "familyName": "adminFamily",
            "email": "admin@maycompany.com",
            "phone": "0033 1 23 45 67 89",
            "language": "en",
            "login": "admin",
            "password": "admin",
            "burthDate": null,
            "authorities": [
                {"id": 3, "name": "user"},
                {"id": 2, "name": "technical user"},
                {"id": 1, "name": "admin"}
            ],
            "enabled": true,
            "pictureId": null,
            "authoritiesAsString": "user, technical user, admin"
        },
        ..........
    ]
    

Posted in Java, JEE | Tagged , , , , , , , , | 1 Comment

Spring-Data-JPA

Implementing persistence layer may need some effort to configure and develop some DAO classes.

Spring-Data-JPA framework can simplify the creation of JPA based repositories and to reduce the amount of code needed to communicate with a database

   
Photo credit Ivan Kmit

This post is an introduction to Spring-Data-JPA. It describes, how you can configure the framewok when you are using Hibernate as your JPA provider.
In this post I will take profit from some Spring 4 new feature as generics autowiring to create generic service.
You can get the sample project from this link to start using Spring-Data-jpa and try some more advenced features.

1- Project dependencies

Spring-Data-JPA references a Spring 3 version. Maven will resolve dependencies by using Spring 3 version instead of version 4.

We need to exclude spring-core and spring-context and import Spring 4 version.


   <!-- Spring -->
   <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>4.0.4.RELEASE</version>
   </dependency>
   <dependency>
      <groupId>org.springframework.data</groupId>
      <artifactId>spring-data-jpa</artifactId>
      <version>1.5.2.RELEASE</version>
      <exclusions>
         <exclusion>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
         </exclusion>
         <exclusion>
            <artifactId>spring-context</artifactId>
            <groupId>org.springframework</groupId>
         </exclusion>
     </exclusions>
   </dependency>

2- Add an Entity

@Entity
@Table(name = "users")
public class User {

    @Id
    @GenericGenerator(name = "generator", strategy = "increment")
    @GeneratedValue(generator = "generator")
    @Column(name = "id", nullable = false)
    private Long id;

    @Column(name = "first_name", nullable = false)
    private String firstName;

    /* Add some extra attributes */     

    /* Add getters and setters */

}

3- Create repository

Declare an interface extending Repository.

import com.mycompany.myproject.persist.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;

public interface UserRepo extends JpaRepository<User, Long> {

    User findByLogin(String login);

}

Spring-Data-JPA analyses the method name and generates a query using the JPA criteria.
Query generation is base on key words like (And, Or, Is, Equals, Between …). For more details, you can read the official Spring-Data-JPA documentation in this link.

4- Create Service

We make a choice to create a generic service that will reference the repository created in previous step.

One of the new features of Spring4 is generic types qualifier. We will take profit from this feature to inject repository by its generic interface.

public class GenericServiceImpl<T, D, ID extends Serializable> implements GenericService<T, D, ID> {

    @Autowired
    private JpaRepository<T, ID> repository;

    @Autowired
    private DozerBeanMapper mapper;

    protected Class<T> entityClass;

    protected Class<D> dtoClass;

    @SuppressWarnings("unchecked")
    public GenericServiceImpl() {
        ParameterizedType genericSuperclass = (ParameterizedType) getClass().getGenericSuperclass();
        this.entityClass = (Class<T>) genericSuperclass.getActualTypeArguments()[0];
        this.dtoClass = (Class<D>) genericSuperclass.getActualTypeArguments()[1];
    }

    public D findOne(ID id) {
        return mapper.map(repository.findOne(id), dtoClass);
    }

    public List<D> findAll() {
        List<D> result = new ArrayList<D>();
        for (T t : repository.findAll()) {
            result.add(mapper.map(t, dtoClass));
        }
        return result;
    }
    
    public void save(D dto) {
        repository.saveAndFlush(mapper.map(dto, entityClass));
    }

}

Next, we add UserService that extends GenericServcie.

@Service
public class UserServiceImpl extends GenericServiceImpl<User, UserDto, Long> {
}

5- Configure the project

  • line 15 : EnableJpaRepositories annotation enables scanning package to look for repository interfaces (created in staep 3).
  • line 21 : We use HSQL embedded database. We need to provide schema script and data script.

import javax.sql.DataSource;
import org.dozer.DozerBeanMapper;
import org.springframework.context.annotation.*;
import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.embedded.*;
import org.springframework.orm.jpa.*;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@Configuration
@EnableTransactionManagement
@ComponentScan({"com.mycompany.myproject.persist", "com.mycompany.myproject.service"})
@EnableJpaRepositories("com.mycompany.myproject.persist")
public class JPAConfig {

    @Bean(name = "dataSource")
    public DataSource dataSource() {
        return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.HSQL).setName("myDb")
                .addScript("classpath:schema.sql").addScript("classpath:data.sql").build();
    }

    @Bean(name = "entityManagerFactory")
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean() {
        LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
        factoryBean.setDataSource(dataSource());
        factoryBean.setPackagesToScan(new String[] { "com.mycompany.myproject.persist" });
        HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        vendorAdapter.setShowSql(true);
        factoryBean.setJpaVendorAdapter(vendorAdapter);
        return factoryBean;
    }

    @Bean
    public PlatformTransactionManager transactionManager() {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(entityManagerFactoryBean().getObject());
        return transactionManager;
    }

    @Bean
    public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
        return new PersistenceExceptionTranslationPostProcessor();
    }

    @Bean
    public DozerBeanMapper getMapper() {
        return new DozerBeanMapper();
    }
}

6- Test your application

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {JPAConfig.class })
public class GenericServiceTest {
	
	@Autowired
	private GenericService<User, UserDto, Long> userService;
	
	@Autowired
    private GenericService<Authority, AuthorityDto, Long> authorityService;
	
	@Test
	public void testFindOneUser() {
		UserDto userDto = userService.findOne(1L);
		Assert.assertNotNull(userDto);
		Assert.assertEquals(1, userDto.getId().longValue());
	}
	
	@Test
    public void testFindOneAuthority() {
        AuthorityDto authorityDto = authorityService.findOne(1L);
        Assert.assertNotNull(authorityDto);
        Assert.assertEquals(1, authorityDto.getId().longValue());
    }
	
	@Test
    public void testFindAll() {
        List<AuthorityDto> authorities = authorityService.findAll();
        Assert.assertFalse(authorities.isEmpty());
    }
	
	@Test
    public void testSave() {
        AuthorityDto authorityDto = new AuthorityDto();
        authorityDto.setName("test authority");
    }
}


If you are a concise code adept you will appreciate using Spring-Data-JPA. To get your repositories you just need to add some interfaces for entities. You don’t need to write redundant basic code for each persistent bean.

The mix of Spring-DATA-JPA and Spring4 gives some extra possibilities to write generic code for the persistence layer.

Posted in Java, JEE | Tagged , , , , , , , , , , , | 2 Comments

Logback – Dynamic creation of log files

Some project have some log constraints that are difficult to implements with Log4j.

Logback is an alternative to log4j. It gives you more possibilities and it can easily implements your log policies.

    log1
Origami by Brian Chan

In this post, I present a simple of Logback configuration for a maven project. This configuration implements a dynamic log files generation.

Sample project description

This post example is inspired from a batch log policy I dealt with. The batch processes N files and generates two logs for each processed file. The first one is a summary of logs with no stack trace for functional users and the second one is a detailed log for programmers.

The picture bellow presents this case of study.

logback
Below the summary of log policies to implement:

  1. Logging errors without stacktrace.
  2. Dynamic file logging (switch to new log file).
  3. Read logging directory from application properties file.
  4. Create log files name with timestamp.

1. Add Maven dependency

First we need to add Slf4j and logback dependency to the project.

<dependency>
	<groupId>org.slf4j</groupId>
	<artifactId>slf4j-api</artifactId>
	<version>1.7.5</version>
</dependency>

<dependency>
	<groupId>ch.qos.logback</groupId>
	<artifactId>logback-classic</artifactId>
	<version>1.0.13</version>
</dependency>

<dependency>
	<groupId>ch.qos.logback</groupId>
	<artifactId>logback-core</artifactId>
	<version>1.0.13</version>
</dependency>

<dependency>
	<groupId>ch.qos.logback</groupId>
	<artifactId>logback-access</artifactId>
	<version>1.0.13</version>
</dependency>

<dependency>
	<groupId>org.slf4j</groupId>
	<artifactId>jcl-over-slf4j</artifactId>
	<version>1.7.5</version>
</dependency>

2. Create a costom layout Class

To customise logging layout, we create a class which extends LayoutBase and override the doLayout method.

public class CustomLogLayout extends LayoutBase<ILoggingEvent>{

	@Override
	public String doLayout(ILoggingEvent event) {
		StringBuffer sbuf = new StringBuffer(128);
	    sbuf.append(new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date(event.getTimeStamp())));
	    sbuf.append(" ");
	    sbuf.append(String.format("%-6s", event.getLevel()));
	    sbuf.append(" ");
	    sbuf.append(event.getFormattedMessage());
	    if((event.getLevel() == Level.ERROR || event.getLevel() == Level.WARN) && event.getThrowableProxy() !=null) {
	    	sbuf.append(" - ");
	    	sbuf.append(StringUtils.substringBefore(event.getThrowableProxy().getMessage(), IOUtils.LINE_SEPARATOR));
	    }
	    sbuf.append(CoreConstants.LINE_SEPARATOR);
	    return sbuf.toString();
	}

}

3. Logback configuration

In this step we create Logback.xml config file that will use the costomLayout we created in the previous step and will implements the logs policies.

  • Line 3 indicates the path to properties file where it will look for some values. In our case the path is a system property.
  • Line 5 specifies a key for the timestamp value.
  • STIF appender creates a custom log files with the CustomLogLayout class.
  • loggerFileName is a MDC (Mapped Diagnostic Contexts) property. Changing this value will generate a new file.
  • SIFT-TRACE appender creates a verbose log file and it uses logback.classic.PatternLayout.

<configuration>

	<property file="${appli.config.path}" />

	<timestamp key="bySecond" datePattern="yyyyMMddHHmmss" />

	<appender name="SIFT" class="ch.qos.logback.classic.sift.SiftingAppender">

		<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
			<level>INFO</level>
		</filter>
		<discriminator>
			<Key>loggerFileName</Key>
			<DefaultValue>unknown</DefaultValue>
		</discriminator>
		<sift>
			<appender name="FILE-${loggerFileName}" class="ch.qos.logback.core.FileAppender">
				<File>${log.dir}/${loggerFileName}_${bySecond}.log</File>
				<Append>false</Append>
				<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
					<layout class="com.mycompany.log.CustomLogLayout" />
				</encoder>
			</appender>
		</sift>
	</appender>

	<appender name="SIFT-TRACE" class="ch.qos.logback.classic.sift.SiftingAppender">
		<discriminator>
			<Key>loggerFileName</Key>
			<DefaultValue>unknown</DefaultValue>
		</discriminator>
		<sift>
			<appender name="TRACE-${loggerFileName}" class="ch.qos.logback.core.FileAppender">
				<File>${log.dir}/TRACE_${loggerFileName}_${bySecond}.log</File>
				<Append>false</Append>
				<layout class="ch.qos.logback.classic.PatternLayout">
					<Pattern>%d %-5level %logger{5} - %msg%n</Pattern>
				</layout>
			</appender>
		</sift>
	</appender>

	<logger name="org.springframework" level="ERROR" />
	
	<root level="DEBUG">
		<appender-ref ref="SIFT" />
		<appender-ref ref="SIFT-TRACE" />
	</root>

</configuration>

4. Test config

In this step we test the logback configuration.

setup() method set system property for the properties file path where logback will look for loging directory path.

The test simulates processing N files and at the end it verifies that we have 2xN log files.

public class LogTest {

	private static final int TEST_FILE_NUM = 5;

	private static final File TEST_DIR = new File(System.getProperty("java.io.tmpdir"), "logbak-test-dir");

	@Before
	public void setUp() throws IOException {
		System.setProperty("appli.config.path", ClassLoader.getSystemClassLoader().getResource("logback.properties").getPath());
		TEST_DIR.mkdirs();
		FileUtils.cleanDirectory(TEST_DIR);
	}


	@Test
	public void testLogbackFileConfig() throws InterruptedException {

		Logger logger = LoggerFactory.getLogger(LogTest.class);

		// assume SLF4J is bound to logback in the current environment
		LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
		JoranConfigurator configurator = new JoranConfigurator();
		configurator.setContext(context);
		context.reset();

		try {
			configurator.doConfigure(ClassLoader.getSystemClassLoader().getResource("logback.xml").getFile());
		} catch (JoranException je) {
			StatusPrinter.print(context);
			Assert.fail("Erreur de chargement des paramètre logback");
		}

		for (int i = 1; i <= TEST_FILE_NUM; i++) {
			MDC.put("loggerFileName", "file" + i);
			logger.info("log in File{}", i);
			logger.debug("log in File{}", i);
			logger.error("log in File" + i, new Exception("My test exception", new Exception("my cause of exception")));
		}

		Assert.assertEquals(TEST_FILE_NUM * 2, TEST_DIR.listFiles().length);
	}
	
}

Posted in Java | Tagged , , , , , , , , | Leave a comment