Путешествие вниз по переулку памяти
Еще в 1998 году, когда я был разработчиком C / C ++ и пробовал свои силы в Java, несколько слов о языке были, мягко говоря, раздражающими для меня. Я помню, волнуюсь об этом довольно много
- Почему нет достойного редактора для этого? C / C ++ было немало. Все, что у меня было для Java — старый добрый блокнот.
- Зачем мне делать класс, когда все, что я хочу, это функция? Почему функция не была объектом?
- Почему я не могу просто упаковать все в один zip / jar и позволить конечному пользователю запустить его двойным щелчком мыши?
и несколько других.
В то время я обнаруживал, что часто упрекаю себя за то, что я не могу отказаться от своего «мышления на C / C ++» и придерживаюсь «Java-способа» ведения дел. Теперь, когда мы писали эту статью в 2013 году, спустя полтора десятилетия, неожиданно все эти ранние раздражения исчезли. Не потому, что я принял «Java», а потому, что ява изменилась.
В стороне от пустых разговоров, цель этой статьи — поговорить об одном из этих вопросов: «Почему я не могу просто упаковать все в один zip / jar и позволить конечному пользователю запустить его двойным щелчком мыши?».
Зачем нам это — один zip / jar — это исполняемый файл?
Если вы — разработчик, с радостью пишите в своей IDE (я презираю всех, кто закодировал Java на Eclipse, NetBeans с самого первого дня и которому не приходилось кодировать на Notepad :)), при поддержке Google (я совершенно точно ненавижу все вы все, кому не надо было искать вещи в интернете до гугла ? :)), наверняка нет убедительного случая.
Однако сталкивались ли вы с ситуацией, когда
- Вас втянули в центр обработки данных, потому что парень выполнил ваши шаги по развертыванию, но ваше приложение / веб-сайт просто не будет работать?
- Внезапно все переменные среды перепутались, когда «никто вообще не трогал» производственные боксы, и вы тот, кто должен «просто заставить это работать».
- Вы сидите с заинтересованным лицом вашего бизнеса и недоверчиво смотрите на «исключение ClassNotFound» и были убеждены, что Java вам совсем не нравится.
Короче говоря, я пытаюсь сказать, что, когда вы находитесь в «относительном» здравомыслии своего dev-бокса / окружения, один исполняемый файл jar на самом деле ничего не делает для вас. Но в тот момент, когда вы входите в сумеречную зону неизвестных серверов и ситуаций (без IDE и другого ассортимента инструментов), вы начинаете понимать, насколько мог помочь один исполняемый файл jar.
Во всей своей наивности я так и думал и выяснил ответ трудным путем. Позволь мне провести тебя через это. Зажги своих редакторов. Давайте создадим исполняемый проект Jar. Я использую jdk1.7.0, STS, Maven 3.0.4. Если вы новичок в Maven или просто не в руки, я рекомендую вам прочитать
это и
это .
Файл: C: \ projects \ MavenCommands.bat
ECHO OFF REM ============================= REM Set the env. variables. REM ============================= SET PATH=%PATH%;C:\ProgramFiles\apache-maven-3.0.4\bin; SET JAVA_HOME=C:\ProgramFiles\Java\jdk1.7.0 REM ============================= REM Standalone java application. REM ============================= call mvn archetype:generate ^ -DarchetypeArtifactId=maven-archetype-quickstart ^ -DinteractiveMode=false ^ -DgroupId=foo.bar ^ -DartifactId=executableJar001 pause
После запуска этого пакетного файла у вас будет полностью компилируемое стандартное Java-приложение. Продолжайте, скомпилируйте его и соберите jar (mvn -e clean install). В итоге вы получите исполняемый файл Jar001-1.0-SNAPSHOT.jar по адресу C: \ projects \ executetableJar001 \ target. Теперь давайте пойдем »
java -jar jarFileName «. И вот ты споткнулся в первый раз. В словаре geeky он говорит вам, что не было класса с основным методом, и, следовательно, он не знал, что выполнять.
К счастью, это легко. Есть
стандартный процесс Java, чтобы решить это. И есть
плагин Maven, чтобы решить это. Я буду использовать последний.
Обновленный файл: /executableJar001/pom.xml
... <dependencies> ... </dependencies> <build> <plugins> <!-- Set main class in the jar. --> <plugin> <groupid>org.apache.maven.plugins</groupid> <artifactid>maven-jar-plugin</artifactid> <version>2.4</version> <configuration> <archive> <manifest> <mainclass>foo.bar.App</mainclass> </manifest> </archive> </configuration> </plugin> </plugins> </build> ...
jar from command line again. This time you will get intended result. So, we are all sorted, right?
Wrong. Very wrong.
... <dependencies> <!-- Logging --> <dependency> <groupid>ch.qos.logback</groupid> <artifactid>logback-classic</artifactid> <version>1.0.9</version> </dependency> </dependencies> <build> ... </build>
package foo.bar; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class App { private final static Logger logger = LoggerFactory .getLogger(App.class); public static void main( String[] args ) { System.out.println( "Hello World!" ); logger.debug("Hello world from logger."); } }
Exception in thread "main" java.lang.NoClassDefFoundError: org/slf4j/LoggerFactory
Dr. P. Simon Tuffs. This gentleman explains how he catered to this problem in this
link. It is a good read, I recommend it. What I have explained in very laymen terms (and have barely scratched the surface), Simon takes a deep dive into the problem and how he solved it. Long story short,
he coded a solution and made it open source.
his article, it is quite informative — but I will call out the salient point of his solution.
- It allows folks to create a single jar that contains everything — your code, resources, dependencies, application server (potentially) — everything.
- It allows the end use to run this entire humongous jar by the simple java -jar jarFileName command.
- It allows developers to develop the same way they have been developing e.g. if it is a web application, the war file structure, remains same. So there are no changes in the development process.
The One-JAR website.
Ant with One-JAR.
Maven with One-JAR.
a Maven plugin for this. Sadly it is not in the Maven Central repository (Why? Folks why? You have put in 98% of work. Why be sluggish about the last 2%?). It comes with nice
usage instructions.
... <dependencies> ... </dependencies> <build> <plugins> ... <!-- If you wanted to bundle all this in one jar. --> <plugin> <groupid>org.dstovall</groupid> <artifactid>onejar-maven-plugin</artifactid> <version>1.4.4</version> <executions> <execution> <goals> <goal>one-jar</goal> </goals> </execution> </executions> </plugin> </plugins> </build> <!-- Required only if you are usng onejar plugin. --> <pluginrepositories> <pluginrepository> <id>onejar-maven-plugin.googlecode.com</id> <url>http://onejar-maven-plugin.googlecode.com/svn/mavenrepo</url> </pluginrepository> </pluginrepositories>
You know what they say about free lunches? There are none. While the concept is quite neat and very practical, it does not mean that every other player have decided to join in. So if your website «needs» to be hosted on one of the biggie paid application servers (I don’t know why you want to keep paying for those proprietary software and folks that understand them. Should you not pay for only quality folks and rely on the open source apps that do not lock you in) One-JAR might not be a feasible solution for you. Also, I hear unconfirmed murmurs about how things might get sluggish (during load up if your app is big. So, before you decide to commit to using this, I recommend you do a POC and make sure that other bits of your techstack are not unhappy with One-JAR.
- How to make DevOps work.
- How to make the entire build and release automated.
- How to leverage the open source libraries to provide solid dependable software while ensuring there are no heavy proprietary software causing lock-in and hence make the solution less agile for future business requirement.
And in my mind, One-JAR plays very nicely in that area. So, I definitely expect to see more of this tool and / or more tools around this concept.
Dropwizard, although not the same thing, but in essence is very similar. They have extended the whole one jar concept with embedded app server, out of the box support for REST, JSON, Logback, sort of in a nice neat package, that you could just use straight off the shelf.
Hope you enjoyed reading this article. Please leave a comment if you have any suggestions and / or feedback. If you want to get in touch, you can look me up at
Linkedin or
Google+ .