Use of ‘_’ as an identifier might not be supported in releases after Java SE 8

Внезапно. Хотелось использовать gettext для локализации шаблонов в разрабатываемом мною статическом генераторе jpress(скоро опубликую на гитхаб), но javac 8-ой версии ругнулся на метод public String _(final String string) { тем что не нужно так его именовать, т.к. в следующих релизах джавы он может не поддерживаться(нарушат обратную совместимость?!).

Гугление вывело меня на JEP 213 в котором есть факт что “_” будет удалено, но не сказано почему.

Однако самое интересное было найдено в списках рассылки:

> Your suspicion is mostly right, except that we are certainly NOT going to
> do Scala’s “wunderbar”. However, things it might be used for include
> things like “I don’t want to give this variable a name” (such as catch
> parameters that are never used.)
Brian Goetz

Что делать? Использовать два нижних подчеркивания! 😀

Семантика Enum в Java

Ничего интересного, просто JavaDoc метода name и toString из класса Enum.


/**
* Returns the name of this enum constant, exactly as declared in its
* enum declaration.
*
* Most programmers should use the {@link #toString} method in
* preference to this one, as the toString method may return
* a more user-friendly name.
This method is designed primarily for
* use in specialized situations where correctness depends on getting the
* exact name, which will not vary from release to release.
*
* @return the name of this enum constant
*/
public final String name() {
return name;
}

name – final метод, а значит переопределять его мы не можем, а вот toString естественно можно:


/**
* Returns the name of this enum constant, as contained in the
* declaration. This method may be overridden, though it typically
* isn't necessary or desirable. An enum type should override this
* method when a more "programmer-friendly" string form exists.
*
* @return the name of this enum constant
*/
public String toString() {
return name;
}

Т.е. для получения enum в виде стринги в большинстве случаев используем name, toString может использоваться для красивых логов (если enum содержит какие-либо поля).

60578090

Вы все еще используете Files.lines()?

Привет, и в очередной раз мы поговорим про новшества Java 8, а точнее Files.lines().

Что может быть проще:

public class FilesLines {

public static void main(String[] args) throws Exception {

Path path = Paths.get("/home/ruslan/test.txt");

for (int i = 0; i < 10000; i++) {
Files.lines(path).count();
}
}
}

Создаем стринговый стрим из файла делаем какие-то операции со стримом и продолжаем работу, стрим же сам о всем позаботиться.

Запустим этот код под Ubuntu 14.04

java -version
java version "1.8.0_31"
Java(TM) SE Runtime Environment (build 1.8.0_31-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.31-b07, mixed mode)

Результат:

Exception in thread "main" java.nio.file.FileSystemException: /home/ruslan/test.txt: Too many open files
at sun.nio.fs.UnixException.translateToIOException(UnixException.java:91)
at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:102)
at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:107)
at sun.nio.fs.UnixFileSystemProvider.newByteChannel(UnixFileSystemProvider.java:214)
at java.nio.file.Files.newByteChannel(Files.java:361)
at java.nio.file.Files.newByteChannel(Files.java:407)
at java.nio.file.spi.FileSystemProvider.newInputStream(FileSystemProvider.java:384)
at java.nio.file.Files.newInputStream(Files.java:152)
at java.nio.file.Files.newBufferedReader(Files.java:2784)
at java.nio.file.Files.lines(Files.java:3744)
at java.nio.file.Files.lines(Files.java:3785)
at by.ibragimov.jpress.FilesLines.main(FilesLines.java:14)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)

wtf

Что-же говорит нам документация? Посмотрим: File#lines(Path path) не содержит ничего подозрительного, но внутри просто делегирует вызов в Files#lines(Path path, Charset cs), а вот тут уже JavaDoc’и на намекают:

    /**
* ...
* The returned stream encapsulates a {@link Reader}. If timely
* disposal of file system resources is required, the try-with-resources
* construct should be used to ensure that the stream's
* {@link Stream#close close} method is invoked after the stream operations
* are completed.
* ...
*/[code]

Ну и исправленная версия напоследок:

[code lang="java"]public class FilesLines {

public static void main(String[] args) throws Exception {

Path path = Paths.get("/home/ruslan/test.txt");

for (int i = 0; i < 10000; i++) {
try(Stream<String> stream = Files.lines(path)) {
stream.count();
}
}
}
}

Вывод как всегда один: читайте документацию.

Best markdown library for Java

tiled-editor-and-web-preview

Для своего мини проекта потребовалась имплементация markdown to html парсера\конвертора. Я рассматривал процессоры найденные в mvnrepository и хочу сразу сказать – все плохо.

Итак были успешно протестированы следующие библиотеки:

am.ik.marked4j:marked4j:0.9.1
com.github.rjeschke:txtmark:0.11
com.sangupta:nutz:0.5.0
net.redhogs.actuarius:actuarius_2.10:0.2.7
org.markdownj:markdownj-core:0.4
org.pegdown:pegdown:1.4.2
ru.circumflex:circumflex-md:2.0.RC2

Я не случайно выделил успешно, в процессе одна из библиотек не завелась т.к. не было scala в classpath (а как зависимость она не додумалась ее включить). Несколько библиотек крашились на файлах сложнее хидеров и листов.

Из прошедших отличились org.pegdown:pegdown:1.4.2 и ru.circumflex:circumflex-md:2.0.RC2: они тянут приличный объем библиотек. Причем ru.circumflex:circumflex-md:2.0.RC2 отличился дважды, он притянул с собой log4j как зависимость!

Лучшей из все оказалась имплементация на JS! Да, именно так! am.ik.marked4j:marked4j:0.9.1 запускает библиотеку marked.js на скриптовом движке джавы и отдает результат полученный от скрипта. Как следствие ожидать сотни обработанных markdown файлов в секунду не стоит.

Что же я выбрал? Я выбрал AsciiDoc.

Почему AsciiDoc лучше Markdown?

1. У AsciiDoc есть хорошая документация и много фич
2. Он умеет не только AsciiDoc -> Html, но и в HTML5, DocBook 5 или 4.5, EPUB3, PDF и т.д.
3. Разработчики предоставляются возможность из коробки использовать его на JVM (JRuby и все такое)
4. С AsciidocFX можно писать и просматривать документы AsciiDoc на любой платформе.

Выводы

Если вы упорот, то можете написать очередной парсер с AST для markdown на Java, а потом еще больше упороться и прикрутить туда поддержку пары дополнений к стандартному синтаксису(кстати, какой стандартный? этот http://commonmark.org/? Или тот, который продвигает автор данного языка разметки?). Или взять какую-нибудь JS либу-парсер markdown и запускать ее под nashorn. А что если нужно больше чем просто markdown (который из коробки очень ограничен), например таблицы, подсветка синтаксиса кода, сноски или оглавление? Да это всё есть в некоторых диалектах mardown, например Github Flavored Markdown, но по моему очень скромному мнению стоит использовать AsciiDoc в котором всё это из коробки и хорошо документировано. А еще AsciiDoc нативно поддерживается на GitHub.

Файл с результатами работы библиотек: markdown-test.

Basic syntax comparison (Markdown vs AsciiDoc)

Flyway and Spring Boot

Добавив jar файл с flyway-core в classpath приложения написанного на Spring Boot и не настроив миграции можно получить следующее исключение:

Caused by: org.flywaydb.core.api.FlywayException: Unable to determine URL for classpath location: db/migration (ClassLoader: sun.misc.Launcher$AppClassLoader@58644d46)

Добавление проперти flyway.enabled = false в application.properties решает проблему но! только при запуске приложения. К сожалению тесты не используют application.properties.

# application.properties
flyway.enabled=false

Быстрый поиск приводит нас например сюда: http://stackoverflow.com/questions/26210786/spring-boot-not-using-application-properties-in-tests, если вас не удовлетворил данный подход/решение то предлагаю пойти дальше и посмотреть мои конфигурационные файлы.

В данном проекте используется java configuration:

@ContextConfiguration(classes = { TestAppConfig.class })
@RunWith(SpringJUnit4ClassRunner.class)
// ... other annotations
public abstract class BaseSpringTest {
// ...
}
@Configuration
@Import({ AppConfig.class })
public class TestAppConfig {
// ...
}
@Configuration
@EnableAutoConfiguration(exclude = { FlywayAutoConfiguration.class })
@ComponentScan("by.ibragimov.rkeep")
public class AppConfig {
// ...
}

В общем-то логично, там где мы включаем авто-конфигурацию, там мы должны иметь возможность ее выключить. И напоследок пару полезных ссылок по теме.

Ссылки:
Execute Flyway database migrations on startup
Appendix A. Common application properties
org.springframework.boot.autoconfigure.flyway.FlywayProperties.java
Auto-configuration