Showing posts with label Java. Show all posts
Showing posts with label Java. Show all posts

07 January, 2015

How to close Java splash image after the application starts

There is a very easy way to get Splash screen in Java application.
With a "-splash:imagepath" command line parameter, or with "SplashScreen-Image: imagepath" manifest parameter.

But when an application is started, Java still shows this image (below the application layer, but it visible when you switching between the applications), until the application is finished. Strange behavior, but it is possible to close this kind of splash screen.

With these lines of code:
import java.awt.SplashScreen;
...
SplashScreen splashScreen = SplashScreen.getSplashScreen();
if (splashScreen != null) {
    splashScreen.close();
}

06 January, 2015

How to bind hotkeys in Java FX

It is possible to create global keyboard shortcuts using a code like this:
import static javafx.scene.input.KeyCombination.keyCombination;
...
private void initHotkeys() {
    ObservableMap accelerators = stage.getScene().getAccelerators();
    accelerators.put(keyCombination("Alt+S"), searchTextField::requestFocus);
    accelerators.put(keyCombination("Alt+C"), columnsTextField::requestFocus);
    accelerators.put(keyCombination("Alt+O"), openFileButton::fire);
    accelerators.put(keyCombination("Alt+E"), exportButton::fire);
    accelerators.put(keyCombination("Alt+T"), truncateButton::fire);
    accelerators.put(keyCombination("Alt+H"), () -> filterChoiceBox.setValue(MATCH_HIGHLIGHT));
    accelerators.put(keyCombination("Alt+F"), () -> filterChoiceBox.setValue(MATCH_FILTER));
    accelerators.put(keyCombination("Alt+U"), () -> filterChoiceBox.setValue(MATCH_FILTER_UNIQUE));
    accelerators.put(keyCombination("Alt+D"), () -> {
        //todo some debug action
    });
}

09 November, 2014

How much memory is allocated to the String object in Java

Size in bytes
String() object
Object header 16
Hash field 4
Reference to char array 4
Char[] array
Object header 16
Array length 4
Array size N*2

String allocates in memory at least (24+20+N*2) bytes, where N - number of characters in the string. If N=10 then string size = 64 bytes.

One million of these strings = 64 000 000 bytes. But also we need array or collection to store these strings.
This requires additional memory.
ArrayList<String>(1 000 000) ~= 4 000 000 bytes (4 bytes per reference to string object).

So, total size will be 68 000 000 bytes.

Gist code: Output:
3,355,792 Initial
1,217,624 After GC
218,921,768 Created list of strings
76,489,936 After GC
68,000,000 Expected size in memory
But if you have many similar strings, then using of String.intern() greatly reduces amount of allocated memory. Output:
3,355,792 Initial
1,217,792 After GC
106,750,232 Created list of strings
13,127,480 After GC
68,000,000 Expected size in memory
10x less memory! 6.8 megabytes instead of 68

01 November, 2014

Read SAS file in Java

Some companies (banks, medical and pharmaceutical companies) store their data in the SAS (.sas7bdat) format. This is old, legacy, but still actual format for tabular data. And this format is proprietary and fiddly.

But what if you have to work with the data from the sas-file? For me, solution is pretty simple - convert the data from the sas-file to some convenient and popular format. For example, to the MongoDB. And then access this data via nice query-like API.

In my new mini-project sas2mongo I show how to convert data from the sas-file into the MongoDB in Java.

26 October, 2014

Sas2Mongo

I've just released my new micro-project: sas2mongo

This is a command line tool for copying data from sas-files to mongo-db.

28 November, 2013

Spring-boot JPA sample with auto-configured repository

Spring-boot allows to create a completely minimalistic applications.
For example, its auto-configuration ability raises and configures JPA and Hibernate-related stuff:
DataSource, Entity and Transaction Managers, Repositories.
With no manual configuration in your code or in xml files.

And the application code is getting smaller and smaller...

User.java
package sb; 
 
import javax.persistence.*; 
 
@Entity 
@Table(name = "sb_user") 
public class User { 
 
    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    public long id; 
    public String name; 
    public String alias; 
 
    public User() { 
    } 
 
    public User(long id, String name) {
        this.id = id; 
        this.name = name; 
    } 
} 
UserRepository.java
package sb;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

import java.util.List;

public interface UserRepository extends JpaRepository<User, Long> {

    @Query("SELECT u FROM User u WHERE u.alias IS NOT NULL")
    List<User> findAliased();
} 
UserController.java
package sb;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
@RequestMapping("user")
public class UserController {
    protected final Logger log = LoggerFactory.getLogger(getClass());

    @Autowired
    private UserRepository users;

    @RequestMapping("test")
    public String test() {
        log.info("Test");
        return "OK";
    }

    @RequestMapping("user")
    public User getUser(@RequestParam("id") long id) {
        log.info("Get user");
        return users.findOne(id);
    }

    @RequestMapping("users")
    public List<User> getUsers(@RequestParam("ids") List<Long> ids) {
    log.info("Get users");
        return users.findAll(ids);
    }

    @RequestMapping("aliased")
    public List<User> getAliasedUsers() {
    log.info("Get aliased users");
        return users.findAliased();
    }
} 
Application.java
package sb;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@EnableAutoConfiguration
@Configuration
@ComponentScan
public class Application {

    public static void main(String[] args) throws Throwable {
        new SpringApplication(Application.class).run(args);
    }
} 
application.properties
spring.datasource.driverClassName=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://srv0/test
spring.datasource.username=test
spring.datasource.password=test 
schema.sql
-- DROP TABLE sb_user;

CREATE TABLE sb_user
(
  id   SERIAL PRIMARY KEY    NOT NULL,
  name CHARACTER VARYING(65) NOT NULL,
  alias CHARACTER VARYING(20)
);

INSERT INTO sb_user (name) VALUES ('Ben Linus');
INSERT INTO sb_user (name) VALUES ('Claire Littleton');
INSERT INTO sb_user (name) VALUES ('Desmond Hume');
INSERT INTO sb_user (name) VALUES ('Frank Lapidus');
INSERT INTO sb_user (name, alias) VALUES ('Hugo Reyes', 'Hurley');
INSERT INTO sb_user (name) VALUES ('Jack Shephard');
INSERT INTO sb_user (name, alias) VALUES ('James Ford', 'Sawyer');
INSERT INTO sb_user (name) VALUES ('Jin-Soo Kwon');
INSERT INTO sb_user (name) VALUES ('Miles Straume');
INSERT INTO sb_user (name) VALUES ('Richard Alpert');
INSERT INTO sb_user (name) VALUES ('Sayid Jarrah');
INSERT INTO sb_user (name) VALUES ('Sun-Hwa Kwon');



Build and run command: gradle clean build runJar

Test urls:
http://localhost:8080/user/user?id=2
http://localhost:8080/user/users?ids=1,3,5,7
http://localhost:8080/user/aliased

26 November, 2013

Spring-boot memory usage

Typical spring-boot application - single jar file.
Size of the file is about 10+ megabytes (it contains another jars, classes and resources inside).
What about memory usage for this app?
I created sample with only one web @Controller and two webmethods: first - reports memory usage, second - runs Java Garbage Collector.

Memory usage after start (http://localhost:8080/test/mem):
max: 1,875,378,176 bytes
total: 355,729,408 bytes
free:  178,138,976 bytes
used:  177,590,432 bytes
and after GC (http://localhost:8080/test/rungc):
max: 1,875,378,176 bytes
total: 355,729,408 bytes
free:  331,821,496 bytes
used:   23,907,912 bytes
With spring-boot we have a lot of available memory)

Controller.java
package sb; 
 
import org.springframework.web.bind.annotation.RequestMapping; 
import org.springframework.web.bind.annotation.RestController; 
 
@RestController 
@RequestMapping("test") 
public class Controller { 
 
    @RequestMapping(value = "mem", produces = "text/plain")
    public String mem() { 
        long max = Runtime.getRuntime().maxMemory(); 
        long total = Runtime.getRuntime().totalMemory(); 
        long free = Runtime.getRuntime().freeMemory(); 
        long used = total - free; 
        return String.format("Memory:\n" +
                "max: %,d bytes\n" +
                "total: %,d bytes\n" +
                "free: %,d bytes\n" +
                "used: %,d bytes\n",
                max, total, free, used); 
    } 
 
    @RequestMapping("rungc") 
    public String rungc() { 
        Runtime.getRuntime().gc(); 
        return "Run GC";
    } 
} 


Application.java
package sb; 
 
import org.springframework.boot.SpringApplication; 
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; 
import org.springframework.context.annotation.ComponentScan; 
import org.springframework.context.annotation.Configuration; 
 
@EnableAutoConfiguration 
@Configuration 
@ComponentScan 
public class Application { 
 
    public static void main(String[] args) throws Throwable {
        new SpringApplication(Application.class).run();
    } 
} 

build.gradle
buildscript { 
    repositories { 
        maven { url "http://repo.spring.io/libs-snapshot" }
    } 
    dependencies { 
        classpath("org.springframework.boot:spring-boot-gradle-plugin:0.5.0.M6")
    } 
} 
 
apply plugin: "java" 
apply plugin: "spring-boot" 
 
buildDir = "out" 
 
jar { 
    baseName = "sb-mem" 
    version = "0.1" 
} 
 
repositories { 
    mavenCentral() 
    maven { url "http://repo.spring.io/libs-snapshot" }
} 
 
dependencies { 
    def springBootVersion = '0.5.0.M6'
    compile("org.springframework.boot:spring-boot-starter-web:$springBootVersion")
} 

25 November, 2013

Spring-boot change log-file location

By default spring-boot writes logs to the /tmp/spring.log file.
But if you need another location - just set LOG_FILE variable in logback.xml configuration.

logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
 
    <property name="LOG_FILE" value="tmp/application.log"/>
 
    <include resource="org/springframework/boot/logging/logback/base.xml"/>
 
    <logger name="sb" level="DEBUG"/>
 
</configuration> 

Application.java
package sb;
 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Service;
 
@Configuration 
public class Application {
 
    @Service 
    static class TestBean {
        protected final Logger log = LoggerFactory.getLogger(getClass());
 
        void test() {
            log.debug("TestBean.test");
        } 
    } 
 
 
    public static void main(String[] args) throws Throwable {
        SpringApplication app = new SpringApplication(Application.class);
        ConfigurableApplicationContext ctx = app.run(args); 
 
        TestBean bean = ctx.getBean(TestBean.class);
        bean.test(); 
    } 
} 

build.gradle
buildscript {
    repositories { 
        maven { url "http://repo.spring.io/libs-snapshot" }
    } 
    dependencies { 
        classpath("org.springframework.boot:spring-boot-gradle-plugin:0.5.0.M6")
    } 
} 
 
apply plugin: "java"
apply plugin: "spring-boot"
 
buildDir = "out"
 
jar { 
    baseName = "sb-log-file"
    version = "0.1"
} 
 
repositories { 
    mavenCentral() 
    maven { url "http://repo.spring.io/libs-snapshot" }
} 
 
dependencies { 
    def springBootVersion = '0.5.0.M6'
    compile("org.springframework.boot:spring-boot-starter:$springBootVersion")
}

21 November, 2013

Spring-boot JDBC with multiple DataSources sample

Spring-Boot's auto-configurer seems good for simple applications. For example it automatically creates DataSource and JdbcTemplate, when you need to connect to the database. But what about less trivial configuration, when you have several different databases?

I found the way to have multiple DataSources for Spring-Boot-based application.

In the sample below I have two special (db-related) Configurations, one properties file with connections' parameters and two Repositories.

Each @Repository connects with appropriate database through separate DataSource.
application.properties
spring.ds_items.driverClassName=org.postgresql.Driver 
spring.ds_items.url=jdbc:postgresql://srv0/test 
spring.ds_items.username=test0 
spring.ds_items.password=test0 
 
 
spring.ds_users.driverClassName=org.postgresql.Driver 
spring.ds_users.url=jdbc:postgresql://srv1/test 
spring.ds_users.username=test1 
spring.ds_users.password=test1 



DatabaseItemsConfig.java
package sb; 
 
import org.springframework.boot.autoconfigure.jdbc.TomcatDataSourceConfiguration; 
import org.springframework.boot.context.properties.ConfigurationProperties; 
import org.springframework.context.annotation.Bean; 
import org.springframework.context.annotation.Configuration; 
import org.springframework.jdbc.core.JdbcTemplate; 
 
import javax.sql.DataSource; 
 
@Configuration 
@ConfigurationProperties(name = "spring.ds_items") 
public class DatabaseItemsConfig extends TomcatDataSourceConfiguration { 
 
    @Bean(name = "dsItems") 
    public DataSource dataSource() { 
        return super.dataSource(); 
    } 
 
    @Bean(name = "jdbcItems") 
    public JdbcTemplate jdbcTemplate(DataSource dsItems) { 
        return new JdbcTemplate(dsItems); 
    } 
} 


DatabaseUsersConfig.java
package sb; 
 
import org.springframework.boot.autoconfigure.jdbc.TomcatDataSourceConfiguration; 
import org.springframework.boot.context.properties.ConfigurationProperties; 
import org.springframework.context.annotation.Bean; 
import org.springframework.context.annotation.Configuration; 
import org.springframework.jdbc.core.JdbcTemplate; 
 
import javax.sql.DataSource; 
 
@Configuration 
@ConfigurationProperties(name = "spring.ds_users") 
public class DatabaseUsersConfig extends TomcatDataSourceConfiguration { 
 
    @Bean(name = "dsUsers") 
    public DataSource dataSource() { 
        return super.dataSource(); 
    } 
 
    @Bean(name = "jdbcUsers") 
    public JdbcTemplate jdbcTemplate(DataSource dsUsers) { 
        return new JdbcTemplate(dsUsers); 
    } 
 
} 


ItemRepository.java
package sb; 
 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.beans.factory.annotation.Qualifier; 
import org.springframework.jdbc.core.JdbcTemplate; 
import org.springframework.jdbc.core.RowMapper; 
import org.springframework.stereotype.Repository; 
 
import java.sql.ResultSet; 
import java.sql.SQLException; 
 
@Repository 
public class ItemRepository { 
    protected final Logger log = LoggerFactory.getLogger(getClass()); 
 
    @Autowired 
    @Qualifier("jdbcItems") 
    protected JdbcTemplate jdbc; 
 
    public Item getItem(long id) { 
        return jdbc.queryForObject("SELECT * FROM sb_item WHERE id=?", itemMapper, id); 
    } 
 
    private static final RowMapper<Item> itemMapper = new RowMapper<Item>() {
        public Item mapRow(ResultSet rs, int rowNum) throws SQLException { 
            Item item = new Item(rs.getLong("id"), rs.getString("title")); 
            item.price = rs.getDouble("id"); 
            return item; 
        } 
    }; 
} 


UserRepository.java
package sb; 
 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.beans.factory.annotation.Qualifier; 
import org.springframework.jdbc.core.JdbcTemplate; 
import org.springframework.jdbc.core.RowMapper; 
import org.springframework.stereotype.Repository; 
 
import java.sql.ResultSet; 
import java.sql.SQLException; 
 
@Repository 
public class UserRepository { 
    protected final Logger log = LoggerFactory.getLogger(getClass()); 
 
    @Autowired 
    @Qualifier("jdbcUsers") 
    protected JdbcTemplate jdbc; 
 
    public User getUser(long id) { 
        return jdbc.queryForObject("SELECT * FROM sb_user WHERE id=?", userMapper, id); 
    } 
 
    private static final RowMapper<User> userMapper = new RowMapper<User>() {
        public User mapRow(ResultSet rs, int rowNum) throws SQLException { 
            User user = new User(rs.getLong("id"), rs.getString("name")); 
            user.alias = rs.getString("alias"); 
            return user; 
        } 
    }; 
} 


Controller.java
package sb; 
 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.web.bind.annotation.RequestMapping; 
import org.springframework.web.bind.annotation.RequestParam; 
import org.springframework.web.bind.annotation.RestController; 
 
@RestController 
public class Controller { 
    protected final Logger log = LoggerFactory.getLogger(getClass()); 
 
    @Autowired 
    private UserRepository users; 
 
    @Autowired 
    private ItemRepository items; 
 
    @RequestMapping("test") 
    public String test() { 
        log.info("Test"); 
        return "OK"; 
    } 
 
    @RequestMapping("user") 
    public User getUser(@RequestParam("id") long id) { 
        log.info("Get user"); 
        return users.getUser(id); 
    } 
 
    @RequestMapping("item") 
    public Item getItem(@RequestParam("id") long id) { 
        log.info("Get item"); 
        return items.getItem(id); 
    } 
 
} 


Application.java
package sb; 
 
import org.springframework.boot.SpringApplication; 
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; 
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; 
import org.springframework.context.annotation.ComponentScan; 
import org.springframework.context.annotation.Configuration; 
 
@EnableAutoConfiguration(exclude = DataSourceAutoConfiguration.class) 
@Configuration 
@ComponentScan(basePackages = "sb") 
public class Application { 
 
    public static void main(String[] args) throws Throwable { 
        SpringApplication app = new SpringApplication(Application.class); 
        app.run(); 
    } 
} 

20 November, 2013

Spring-boot JDBC sample

Simple Web+JDBC application.

With spring-boot you just do your business. Without overhead, without extra manipulations and configurations.
In example below:
  • UserRepository provides information about users from database via JdbcTemplate, plain SQL-queries and RowMapper.
  • UserController makes them accessible via HTTP.
In this example spring-boot automatically configures DataSource and JdbcTemplate according to application.properties file.

Sample urls:
  • http://localhost:8080/user/test
  • http://localhost:8080/user/user?id=2
  • http://localhost:8080/user/users?ids=1,3,5,7

Sources are minimalistic:
Application.java
package sb; 
 
import org.springframework.boot.SpringApplication; 
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; 
import org.springframework.context.annotation.ComponentScan; 
import org.springframework.context.annotation.Configuration; 
 
@EnableAutoConfiguration 
@Configuration 
@ComponentScan 
public class Application { 
 
    public static void main(String[] args) throws Throwable { 
        SpringApplication app = new SpringApplication(Application.class); 
        app.setShowBanner(false); 
        app.run(args); 
    } 
} 
User.java
package sb;

public class User {
    public long id;
    public String name;
    public String alias;

    public User(long id, String name) {
        this.id = id;
        this.name = name;
    }
} 
UserController.java
package sb;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
@RequestMapping("user")
public class UserController {
    protected final Logger log = LoggerFactory.getLogger(getClass());

    @Autowired
    private UserRepository users;

    @RequestMapping("test")
    public String test() {
        log.info("Test");
        return "OK";
    }

    @RequestMapping("user")
    public User getUser(@RequestParam("id") long id) {
        log.info("Get user");
        return users.getUser(id);
    }

    @RequestMapping("users")
    public List<User> getUsers(@RequestParam("ids") long[] ids) {
        log.info("Get users");
        return users.getUsers(ids);
    }
} 
UserRepository.java
package sb;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

@Repository
public class UserRepository {
    protected final Logger log = LoggerFactory.getLogger(getClass());

    @Autowired
    protected JdbcTemplate jdbc;

    public User getUser(long id) {
        return jdbc.queryForObject("SELECT * FROM sb_user WHERE id=?", userMapper, id);
    }

    public List<User> getUsers(long[] ids) {
        String inIds = StringUtils.arrayToCommaDelimitedString(ObjectUtils.toObjectArray(ids));
        return jdbc.query("SELECT * FROM sb_user WHERE id IN (" + inIds + ")", userMapper);
    }

    private static final RowMapper<User> userMapper = new RowMapper<User>() {
        public User mapRow(ResultSet rs, int rowNum) throws SQLException {
            User user = new User(rs.getLong("id"), rs.getString("name"));
            user.alias = rs.getString("alias");
            return user;
        }
    };

} 
application.properties
spring.datasource.driverClassName=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://srv0/test
spring.datasource.username=test
spring.datasource.password=test 
build.gradle
buildscript { 
    repositories { 
        maven { url "http://repo.spring.io/libs-snapshot" } 
    } 
    dependencies { 
        classpath("org.springframework.boot:spring-boot-gradle-plugin:0.5.0.M6") 
    } 
} 
 
apply plugin: "java" 
apply plugin: "spring-boot" 
 
buildDir = "out" 
 
jar { 
    baseName = "sb-jdbc" 
    version = "0.1" 
} 
 
repositories { 
    mavenCentral() 
    maven { url "http://repo.spring.io/libs-snapshot" } 
} 
 
dependencies { 
    def springBootVersion = '0.5.0.M6' 
 
    compile("org.springframework.boot:spring-boot-starter-web:$springBootVersion") 
    compile("org.springframework.boot:spring-boot-starter-jdbc:$springBootVersion") 
 
    compile("org.postgresql:postgresql:9.2-1003-jdbc4") 
} 

19 November, 2013

Java -XX: AutoBoxCacheMax option

-XX:AutoBoxCacheMax=size option lets to control cache size for Integers.

In current Oracle HotSpot JVM (1.7) it only affects on Integer objects, created via autoboxing or Integer.valueOf(int i).

public class IntegersDemo {
    public static void main(String[] args) {
        {
            Integer a100 = 100;
            Integer b100 = 100;
            System.out.println(a100 == b100); //true
 
            Integer a200 = 200;
            Integer b200 = 200;
            System.out.println(a200 == b200); //false by default, 
            // but true when -XX:AutoBoxCacheMax=1000
        }
 
        {
            Integer a100 = Integer.valueOf(100);
            Integer b100 = Integer.valueOf(100);
            System.out.println(a100 == b100); //true
 
            Integer a200 = Integer.valueOf(200);
            Integer b200 = Integer.valueOf(200);
            System.out.println(a200 == b200); //false by default,
            // but true when -XX:AutoBoxCacheMax=1000
        }
 
        {
            Integer a100 = new Integer(100);
            Integer b100 = new Integer(100);
            System.out.println(a100 == b100); //always false, 
            // because of objects are allocated via "new"
        }
    }
}
 

07 October, 2011

Java 7

Great enhancement: binary literals and underscores:

int netaddr = 0b11000000_10101000_00000000_00000000; //192.168.0.0
int netmask = 0xFF_FF_FF_00; //255.255.255.0

08 July, 2011

Spring: annotation driven and configured scheduler

Properties file (file.properties):

...
manager.cron=0 */1 * * * ?
...


Application context (context.xml)

...
<context:property-placeholder location="file.properties"/>
<task:annotation-driven/>
...


Bean:

@Component
public class Manager {
...
@Scheduled(cron = "${manager.cron}")
public void doSomething() {
log.info("doSomething");
}
...
}

28 March, 2010

Flex compiler locale

In order to switch flex compiler messages to US locale put this string "-Duser.language=en -Duser.region=US" into the $FLEX_HOME/bin/jvm.config file.

...
java.args=-Xmx384m -Dsun.io.useCanonCaches=false -Duser.language=en -Duser.region=US
...

13 August, 2009

Bind XML to Java classes

Just follow this example:


cbr_daily.xml
<ValCurs Date="30/05/2009" name="Foreign Currency Market">
<Valute ID="R01035">
<NumCode>826</NumCode>
<CharCode>GBP</CharCode>
<Nominal>1</Nominal>
<Name>Фунт стерлингов Соединенного королевства</Name>
<Value>49,7887</Value>
</Valute>
<Valute ID="R01235">
<NumCode>840</NumCode>
<CharCode>USD</CharCode>
<Nominal>1</Nominal>
<Name>Доллар США</Name>
<Value>30,9843</Value>
</Valute>
<Valute ID="R01239">
<NumCode>978</NumCode>
<CharCode>EUR</CharCode>
<Nominal>1</Nominal>
<Name>Евро</Name>
<Value>43,3780</Value>
</Valute>
</ValCurs>



ValCursType.java
package xqx;

import java.util.List;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;

@XmlRootElement(name = "ValCurs")
@XmlType(name = "ValCursType")
public class ValCursType {

@XmlElement(name = "Valute")
public List<ValuteType> valuteType;

@XmlAttribute(name = "Date")
public String date;

@XmlAttribute
public String name;
}




ValuteType.java
package xqx;

import javax.xml.bind.annotation.*;

@XmlRootElement(name = "Valute")
@XmlType(name = "ValuteType")
public class ValuteType {
@XmlElement(name = "NumCode")
public String numCode;

@XmlElement(name = "CharCode")
public String charCode;

@XmlElement(name = "Nominal")
public int nominal;

@XmlElement(name = "Name")
public String name;

@XmlElement(name = "Value")
public String value;

@XmlAttribute(name = "ID")
public String id;
}




CbrCurrencyTask.java
package xqx;

import ...;

public class CbrCurrencyTask {

...
//stream - For example FileInputStream created from the "cbr_daily.xml" file
protected ValCursType parse(InputStream stream) throws JAXBException {
JAXBContext jaxbContext = JAXBContext.newInstance(ValCursType.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();

ValCursType valCursType = (ValCursType) unmarshaller.unmarshal(stream);
return valCursType;
}
...

}


Simple! Isn't it?

27 July, 2009

JDBC: Postgres enums and prepared statements

There is simple way how to map Java enums to PostgreSQL enums via JDBC's prepared statements.

For example we have these PostgreSQL enum and table definitions:

CREATE TYPE log_level AS ENUM ('INFO', 'WARN', 'ERROR');

CREATE TABLE logs (
id SERIAL PRIMARY KEY,
message VARCHAR(255) NOT NULL,
level log_level NOT NULL,
);


And Java enum:

public enum LogLevel {
INFO, WARN, ERROR
}


This form of prepared statement should work:

LogLevel logLevel = LogLevel.INFO;
PreparedStatement sql = conn.prepareStatement("INSERT INTO logs (message, log_level) VALUES (?, ?::log_level)");
sql.setString(1, "Hello world");
//sql.setString(2, "INFO");
sql.setString(2, logLevel.name());

19 January, 2009

Run java with non-system locale

java -Duser.language=en -Duser.region=US JavaClass

19 November, 2008

Maven repository through socks proxy

There is the solution how to access remote maven repository through socks proxy.

Just put this string:

set MAVEN_OPTS=-DsocksProxyHost=yourSocksProxyHost -DsocksProxyPort=yourSocksProxyPort

to the beginning of the "apache-maven-2.x.x\bin\mvn.bat" file.

01 September, 2008

Access logging under Tomcat

Do you want to get "access.log" file under Apache Tomcat Server as well as under Apache HTTP Server? Like this:
192.168.1.1 - - [25/Aug/2008:15:08:11 +0400] "GET / HTTP/1.1" 200 82777
192.168.1.1 - - [25/Aug/2008:15:08:11 +0400] "GET /js/event-debug.js HTTP/1.1" 200 88582
192.168.1.1 - - [25/Aug/2008:15:08:11 +0400] "GET /js/history-debug.js HTTP/1.1" 200 28540
192.168.1.1 - - [25/Aug/2008:15:08:11 +0400] "GET /js/prototype.js HTTP/1.1" 200 126120
192.168.1.1 - - [25/Aug/2008:15:08:11 +0400] "GET /js/json2.js HTTP/1.1" 200 9490
192.168.1.1 - - [25/Aug/2008:15:08:12 +0400] "GET /css/app.css HTTP/1.1" 200 1937

Just insert one line into the "Engine" section of the "server.xml" file:
<Engine name="Catalina" defaultHost="localhost">
...
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="access." suffix=".log" pattern="common"/>
...
</Engine>


Also it is possible to collect and filter the set of raised files via this script:


access.sh
#!/bin/bash

cat access.log | cut -f2 -d"\"" access.log | cut -f2 -d" " | egrep -v -f ignore.txt | sort



ignore.txt
^/$
^/JSON-RPC$
^/JSON-RPC-GET\?
//Any other patterns

11 July, 2008

Sources of com.sun.net.httpserver.HttpServer

Sun JRE contains implementation of simple HTTP server.
(in the com.sun.net.httpserver and sun.net.httpserver packages)


But this "HttpServer":

  • Not a part of Java API.

  • It is Sun's proprietary component

  • It works only under Sun JRE >=1.6

  • His sources are available only as a part of Standard Edition Development Kit Source Release under Java Research License
    (see Java™ Platform, Standard Edition 6u3 Source Snapshot Releases jdk-6u3-fcs-src-b05-jrl-24_sep_2007)


But sometimes this implementation is pretty useful (for example here).