Общее·количество·просмотров·страницы

Java Dev Notes - разработка на Java (а также на JavaScript/Python/Flex и др), факты, события из АйТи

Показаны сообщения с ярлыком job. Показать все сообщения
Показаны сообщения с ярлыком job. Показать все сообщения

вторник, 15 июня 2010 г.

Связка nginx - Tomcat: прокидывание реального IP пользователя до Томката

При разработке Evaphone мы решили все томкаты проксировать с помощью nginx. Это хорошо известная схема - frontend server - backend server. Frontend сервер (в нашем случае - nginx) занимается отдачей статики, а на backend он проксирует запросы на динамику. Такая схема работы позволяет снизить нагрузку на "тяжелый" бэкенд и увеличить производительность приложения.

Внутри нашего приложения используется информация о пользователи, а именно, IP-адрес. Когда запрос проксируется nginx'ом, то, естественно, реальный IP-адрес пользователя подменяется адресом машины, на которой работает nginx. Однако, nginx не "теряет" реальный IP-адрес. Вместо этого он передает его в HTTP-заголовке "x-real-ip". Это настраивается следующим конфигом nginx:


location = /tomcat {
proxy_pass ___tomcat_app_url___;
proxy_redirect off;

proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}


В этот конфиг вместо ___tomcat_app_url___ нужно подставить URL приложения на томкате, куда будет передаваться запрос. Например, может быть следующий URL: http://127.0.0.1:8080/myapp (это если tomcat и nginx работают на одной машине). Этот конфиг говорит томкату, что все запросы по адресу <ваш_ip>/tomcat нужно проксировать на ___tomcat_app_url___.

Теперь рассмотрим настройку Tomcat. Мы знаем, что реальный айпишник приходит к нам в заголовке запроса "x-real-ip". Подмену адреса (вернее, вытягивание реального айпишника) мы делаем с помощью сервлетного фильтра:

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.FilterConfig;
import javax.servlet.FilterChain;
import javax.servlet.ServletResponse;
import javax.servlet.ServletRequest;
import javax.servlet.Filter;
 
public class GetRealIPFilter implements Filter {
 
public static final String X_FORWARDED_FOR = "x-forwarded-for";
public static final String X_REAL_IP = "x-real-ip";
 
public GetRealIPFilter() {
//System.out.println("[GetRealIPFilter.GetRealIPFilter]");
}
 
public void destroy() {
//System.out.println("[GetRealIPFilter.destroy]");
}
 
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
throws ServletException, IOException
{
//System.out.println("[GetRealIPFilter.doFilter]");
if (request instanceof HttpServletRequest) {
 
HttpServletRequest httpRequest = (HttpServletRequest)request;
 
final String realIp = httpRequest.getHeader(X_REAL_IP);
final String realHost = httpRequest.getHeader(X_FORWARDED_FOR);
 
//System.out.println("[GetRealIPFilter.doFilter], realIp='"+realIp+"'");
//System.out.println("[GetRealIPFilter.doFilter], realHost='"+realHost+"'");
 
if (realIp != null) {
//System.out.println("[GetRealIPFilter.doFilter], realIp != null, wrap request");
 
filterChain.doFilter(
new HttpServletRequestWrapper(httpRequest) {
public String getRemoteAddr() {
return realIp;
}
public String getRemoteHost() {
return realHost;
}
},
response
);
return;
}
}
filterChain.doFilter(request, response);
}
 
public void init(FilterConfig filterConfig) throws ServletException {
//System.out.println("[GetRealIPFilter.init]");
}
}


Код достаточно понятный. Что мы делаем:

  1. Проверяем, есть ли заголовок "x-real-ip". Если его нет, то ничего не делаем, т.е. все остается по-старому. Tomcat продолжит принимать запросы напрямую

  2. Если заголовок "x-real-ip" присутствует, то в цепочку фильтров мы передаем не пришедший к нам от nginx request, а его обертку HttpServletRequestWrapper, в которой мы подменили методы getRemoteAddr и getRemoteHost так, чтобы они выдавали данные, пришедшие в заголовках "x-real-ip", "x-forwarded-for" соответственно.


Осталось только замэппить наш фильтр на все приложение. В файле web.xml добавляем следующие строки:

<filter>
<filter-name>get_real_ip_filter</filter-name>
<filter-class>GetRealIPFilter</filter-class>
</filter>
 
<filter-mapping>
<filter-name>get_real_ip_filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>


На этом все!

Пара ссылок:

Настройка nginx для работы с apache и tomcat серверами на примере Ubuntu 10.04 Server

Nginx + Tomcat - тред на форуме nginx

JSP+Tomcat+nginx - тред на форуме RSDN

UPD 11 Июля 2010: Улучшенный код:

public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) 
throws ServletException, IOException
{
//System.out.println("[GetRealIPFilter.doFilter]");
if (request instanceof HttpServletRequest) {
 
HttpServletRequest httpRequest = (HttpServletRequest)request;
 
final String realIp = httpRequest.getHeader(X_REAL_IP);
final String realHost = httpRequest.getHeader(X_FORWARDED_FOR);
 
//System.out.println("[GetRealIPFilter.doFilter], realIp='"+realIp+"'");
//System.out.println("[GetRealIPFilter.doFilter], realHost='"+realHost+"'");
 
if (realIp != null) {
if (realHost != null) {
filterChain.doFilter(new HttpServletRequestWrapper(httpRequest) {
public String getRemoteAddr() {return realIp;}
public String getRemoteHost() {return realHost;}
},response);
return;
} else {
filterChain.doFilter(new HttpServletRequestWrapper(httpRequest) {
public String getRemoteAddr() {return realIp;}
},response);
return;
}
} else if (realHost != null) {
filterChain.doFilter(new HttpServletRequestWrapper(httpRequest) {
public String getRemoteHost() {return realHost;}
},response);
return;
}
}
filterChain.doFilter(request, response);
}

суббота, 12 июня 2010 г.

Установка yum на CentOS 5.4 (Final):

Ставим yum на CentOS 5.4 (Final):


cd ~/
mkdir temp
cd temp
wget http://mirror.centos.org/centos/5/os/i386/CentOS/yum-3.2.22-26.el5.centos.noarch.rpm
wget http://mirror.centos.org/centos/5/os/i386/CentOS/python-iniparse-0.2.3-4.el5.noarch.rpm
wget http://mirror.centos.org/centos/5/os/i386/CentOS/rpm-python-4.4.2.3-18.el5.i386.rpm
wget http://mirror.centos.org/centos/5/os/i386/CentOS/python-urlgrabber-3.1.0-5.el5.noarch.rpm
wget http://mirror.centos.org/centos/5/os/i386/CentOS/yum-fastestmirror-1.1.16-14.el5.centos.1.noarch.rpm
wget http://mirror.centos.org/centos/5/os/i386/CentOS/yum-metadata-parser-1.1.2-3.el5.centos.i386.rpm
wget http://mirror.centos.org/centos/5/os/i386/CentOS/m2crypto-0.16-6.el5.6.i386.rpm
rpm -ivh *rpm


список RPM-пакетов для CentOS можно посмотреть по ссылке http://mirror.centos.org/centos/5/os/i386/CentOS

Здесь http://www.electrictoolbox.com/install-yum-with-rpm-on-centos/ раскрывается похожая тема

вторник, 8 июня 2010 г.

Установка переменных среды для Java, Apache Tomcat

Устанавливаем переменные среды JAVA_HOME, CATALINA_HOME. Только что столкнулся с тем, что если устанавливать переменные среды через export из SSH, то они не сохраняются между SSH-сессиями. В этом случае их надо прописать в файле ~/bashrc или ~/bash_profile.

Прописал следующее, теперь все работает:

Добавил следующие строки в файл ~/bashrc

JAVA_HOME=/usr/java/jdk1.6.0_20
export JAVA_HOME

CATALINA_HOME=/usr/java/apache-tomcat-6.0.26
export CATALINA_HOME

PATH=$PATH:$JAVA_HOME/bin

export PATH


Весь же файл ~/bashrc выглядит так


# .bashrc

# User specific aliases and functions

alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'

# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi

JAVA_HOME=/usr/java/jdk1.6.0_20
export JAVA_HOME

CATALINA_HOME=/usr/java/apache-tomcat-6.0.26
export CATALINA_HOME

PATH=$PATH:$JAVA_HOME/bin

export PATH

Установка и удаление java на CentOS

Устанавливаем JDK на CentOS:


  1. Скачиваем jdk-6u20-linux-i586.bin с сайта http://java.sun.com

  2. Заливаем его на сервер в каталог /usr/java

  3. Меняем права $>chmod 755 jdk-6u20-linux-i586.bin

  4. Выполняем #./jdk-6u20-linux-i586.bin

  5. Набираем yes для согласия с лицензией, далее идет установка

  6. Устанавливаем переменную среды # export JAVA_HOME=/usr/java/jdk1.6.0_20
    Затем кладем ее в PATH:
    # export PATH=$PATH:$JAVA_HOME/bin

  7. Проверочка #java -version
    Получаем:

    # java -version
    java version "1.6.0_20"
    Java(TM) SE Runtime Environment (build 1.6.0_20-b02)
    Java HotSpot(TM) Client VM (build 16.3-b01, mixed mode, sharing)




UPDATE:

Как удалять JRE

Вот ссылка на java.com: How do I uninstall Java for Linux ?

Если JRE была поставлена из RPM:

1) проверяем, поставлена ли JRE из rpm:

rpm -qa | grep jre

2) удаляем

rpm -e jre-1.5.0_21-fcs

3) Профит! (иногда надо перезагрузить машину)

воскресенье, 21 марта 2010 г.

Чему я научился, собирая миллион долларов на стартап без бизнес-плана и финансовых прогнозов (потягивая при этом пиво)

Классный пост от Роберта Мэя: What I Learned Raising A Million Dollars For a Startup With No Business Plan and No Financial Projections (While Drinking a Beer). А на сайту StartupPoint находится его перевод. Очень и очень познавательно.

Вывод, впрочем, все тот же - нужно делать свой проект несмотря ни на что: несмотря на отсутствие инвесторов, отсутствие денег, присутствие многих других проблем, и т. д. Потому что вы и есть тот человек, которому этот проект нужен больше всего. Если вы от него откажетесь, то его не поднимет никто. Делать, делать, делать!

среда, 17 февраля 2010 г.

23 хака для работы

Данный пост написан по мотивам поста Hack Your Work: 23 Ways to Get Ahead, Work Less and Achieve More из блога Dumb Little Man - Tips for Life.


  1. Одна цель

    Установите одну цель, которую хочется достигнуть в этом году. Слишком сложно достигать несколько целей одновременно, т.к. это рассеивает ваши усилия, энергию. Выберите одну цель на следующие 12 месяцев, и затем одну цель на ближайшие 3-6 месяцев (но такую, которая бы приближала вас к годовой цели). Затем выберите что-либо, что можно сделать в течении 1-2 недель, и что приближает к 3-6-месячной цели. После этого приложите все усилия, чтобы достигнуть свою краткосрочную цель. А затем двигайтесь в том же духе дальше.

  2. Найди свою страсть

    Все последующие советы всего лишь немного улучшат ситуацию, если вы работаете на работе, которая вам очень нравится. Если вы не на такой работе, то следует выяснить, какая работа вам больше всего нравится. Необязательно прямо сейчас увольняться с текущей работы, но стоит начать небольшое исследование на тему, что же вам нравится, и что вы любите делать. Поговорите с друзьями, родными, побродите по Интернету, попробуйте разные занятия. Сделайте это целью на ближайший год - выяснить, что вам нравится делать.

  3. Поработай из дома

    Возможно, большую часть работы можно выполнять из дома, особенно сейчас, во времена развитых компьютерных сетей и интернета.

  4. Приходи на работу раньше

    Попробуй приходить на работу на 30-60 мин раньше всех остальных. Тебе придется рано вставать, но выгоды очевидны: ты не попадаешь в утренние пробки, день начинается бодро, ты можешь быть впереди остальных, и успеть сделать больше. Ранний старт рабочего дня - отличный способ быть более продуктивным.

  5. Работай 4 дня

    Если ты можешь управлять своим расписанием, попробуй работать меньше дней в неделю, чем обычно. Например, четыре дня, а не пять. Это дает: дополнительный выходной, это заставляет тебя быть более продуктивным (на 20%). Подумай сам: если ты знаешь, что твоя рабочая неделя закончится в четверг, а не в пятницу, будешь ли отвлекаться на посторонние вещи? Думаю, вряд ли.

  6. Работай 6 часов в день

    Аналогично предыдущему пункту. Но предыдущий пункт может подойти не для всех. Тогда стоит попробовать работать по 6 часов в день, и при этом рано вставать. Представь, работу начинаешь в 7 утра, а заканчиваешь уже в час дня!

  7. Работай 20 часов в неделю

    Если ограничить работу 20 часами в неделю (например, у вас удаленная работа), то скоро почувствуешь, что ты стал более сфокусированных и успеваешь сделать больше за меньшее время.

  8. СВЗ

    СВЗ - Самые Важные Задачи. В начале каждого дня пиши список из трех самых важных задач, которые нужно сделать за сегодня. Сделай по крайней мере одну из них приближающей тебя к Твоей Главной Цели. Это должны быть действительно важные задачи, те, которые повлияют положительно на тебя и твой доход в долгосрочной перспективе. И попробуй сделать их с утра, самыми первыми, до того, как на тебя свалится масса других дел.

  9. Пакетное выполнение

    Есть множество маленьких дел, которые, тем не менее, отвлекают тебя от твоей работы. Это могут быть телефонные звонки, работа с бумагами, выписка счетов, составление и отправка email, и т.д. Ты уже понимаешь, что надо их выписывать на листочек, а затем делать все сразу, за один присест, и больше к ним не возвращаться в течении дня. Это называется "пакетное выполнение", по аналогии в пакетными файлами в Юникс.

  10. Работай удаленно один день в неделю

    Если не можешь уговорить своего босса, чтобы он позволил тебе работать из дома, попробуй сначала работать хотя бы один день из дома. Например, скажи, что ты болен, и не пойди на работу, но сделай в этот день больше, чем обычно.

  11. Фрилансить в свободно время

    Комментарии здесь излишни: нужно выделить свободное время, и начать фриланс-практику.

  12. Обедать на работе

    Можно приносить обед из дома, и обедать на работе. Этим убивается несколько зайцев: экономятся деньги и время, можно пораньше уходить с работы, можно больше успеть сделать.

  13. Ездить на работу на велосипеде

    Это сэкономленные деньги на бензине, сохраненные нервы от стояния в пробках, ежедневные физические упражнения.

  14. Занимайся проектами с потенциально высокой отдачей

    Ежедневная текучка не сделает тебя звездой. Если ты примешься за проект, который может принести высокую отдачу, сильно продвинуть твою компанию вперед, то, если ты его хорошо выполнишь, это благоприятно отразится на твоем положении в компании. Сделай задачи по этому проекту своими СВЗ, и начинай каждый день с работы над ними.

  15. Автоматизируй свой бизнес

    Автоматизированный бизнес высвобождает твое время для более интересных и творческих задач.

  16. Откладывай добавочный доход

    Если твой доход увеличился, не спеши его тратить - и вообще, не спеши увеличивать траты. Отложи добавку в банк. Это не увеличивает, конечно, твою производительность, но зато увеличивает финансовую стабильность.

  17. Расчисти рабочее место

    Чистое рабочее место делает тебя более спокойным, более производительным, более организованным.

  18. Разделяй и властвуй

    Если задача целиком кажется неподъемной, раздели ее на ряд небольших подзадач, и выполни их одна за одной.

  19. Делегируй

    Избавься от привычки все делать самому. Поручи часть свои задач другим, но проконтролируй результат (и, возможно, исполнение).

  20. Избавься от необязательных задач

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

  21. Не отвлекайся

    Телефонные звонки, email, твиттер и т.п. отвлекают тебя от дел. Больше фокусируйся, и ты больше сделаешь.

  22. Убей митинги

    Долгие митинги - это пустая трата времени. Большинство проблем, которые обсуждаются на митинге, можно решить через email или телефонным звонком.

  23. Чтение и написание Email - один раз в день

    Выдели время на электронную почту - прочитай ее и напиши письма, если необходимо. Затем в течении дня не притрагивайся к электронке.

четверг, 29 октября 2009 г.

Прикольное описание вакансии на StackOverflow

Software Developer (Python/Django)
at Playfire.com (Gaming social networking startup!)
London, United Kingdom

Hi! We are an exciting, well-funded web startup looking for an ambitious software engineer who is hungry to build awesome software that millions of people use. Based in Soho, London, we are building the next big thing for millions of gamers around the world, and are looking for an exceptional technical mind to join the team and attack some hard problems in creative ways.

....

Are you the one? You are, if you:

* Love agile development, working independently on your own challenges, and together in a team on the bigger vision
* Are completely fluent in a scripting language such as Python, Perl, PHP or Ruby and have experience with web frameworks and the MVC concept
* Have used MySQL or PostgreSQL extensively and you know your way around Apache, nginx or other server
* It's a bonus if you have good JavaScript skills (we use jQuery)
* Get excited by the idea of scaling web apps to millions of users
* Are the best developer in your peer group, and want to be at a place where you are constantly challenged and pushed to become better
* Get obsessed about the problem you're solving and don't stop until you've cracked it
* Have a thirst to learn new skills and technologies, and can pick things up easily
* Want to have fun building lots of new features and get stuff done
* Are full of positive energy, relish the thought of being part of a small, fast-moving team and enjoy brainstorming about new ideas

Benefits

* Opportunity to become recognised as one of the best in your field, through being a core developer for a high-profile startup
* Relaxed, sociable work environment with lots of freedom and independence
* Building an exciting app that millions of real life people will use and appreciate everyday
* First hand experience of how to start, grow, market and raise funding for startups (perhaps useful for your own company one day)
* Working with awesome technologies (Python/Django/jQuery/Debian/Git)
* As part of one of the top technical teams in the UK, along side super smart people who have a lot of fun, devoid of any politics
* With dual-widescreen monitors, a new computer and a Herman Miller Aeron chair
* In a fun office, with free drinks, in the heart of Soho (there are so many options for lunch it's crazy!)
* A competitive salary and a generous equity stake in the company (you're working hard to make the company successful, so you should share generously in the reward!)

A little more about us

* Backed by some of the most prestigious investors in the world with specific experience in social networks and games (including the founder of Bebo, the former CEO of PlayStation, the founders of Skpe, etc - who you'll likely get to meet)
* Founded by entrepreneurs with a track record for success with internet and video games companies
* 200,000 gamers already using the service!
* We'll be messing around with Facebook Apps, OpenSocial and will be integrating with Xbox Live and other multiplayer services.
* And unlikely many other web businesses, we know exactly how to make money, and steps needed to get us there :)

So, all in all, exciting stuff! We want to hear from you! Details on how to do that are below :-)


По-моему, это просто CRAZY & AWESOME, не так ли?

среда, 28 октября 2009 г.

Про программирование (с другой стороны Луны)

Еще один пост по мотивам блога Эльдара Мусаева - Как стать хорошим программистом? (часть 3 из 3). Обратная сторона Луны. Точнее, меня заинтересовала только одна часть поста - про социальный статус. Далее приведу некоторые выдержки из поста Эльдара.

В целом программисты – это «синие воротнички» с высокой зарплатой. И обращаются с вами соответственно. Если в России вы работали в науке или преподавании, в университетской среде, то получали вы может и очень немного, но ваша свобода как в распоряжении своим временем, так и в направлении исследований была несравненно выше. Даже если вы подрабатывали консалтингом и проектами на стороне. А свобода – это один из важнейших показателей социального статуса.

Уйдя в программисты, особенно программисты в Америке, все это меняется. Это работа по найму. Это рабочий день с 9 до 5 (а то и с 9 до 9). Это подчинение менеджменту. Это партсобрания, пардон, team meetings, на которых вам втюхивают, как вам повезло и какая классная группа, команда, фирма, на которую вы работаете. Причем делают это так фальшиво и неубедительно, что даже если вы в это и верили, то начнете сомневаться.

В общем, не все так плохо. В конце концов, доходы программистов сравнимы с доходами многих врачей и юристов. Просто надо понимать, что программирование – это не социальный лифт, и стать миллионером (или просто достичь финансовой независимости) в этой профессии ничуть не легче чем в любой другой. И «стекляный потолок» может и выше, чем в многих других областях, но все равно вполне реален и весьма прочен.

Такие дела...

Сколько стоит плохой начальник?

Сообщение по мотивам поста в блоге Эльдара Мусаева. Интересны цифры стоимости плохих начальников, то есть начальников, которых не любят и которым не доверяют их подчиненные.

Ну, отрицательных факторов несколько. Во-первых, это turnover - текучка кадров. Далее, проблемы со здоровьем подчиненных такого начальника. Удивительно, но работа на скотину повышает шансы сердечно-сосудистых заболеваний на одну шестую, и шансы инфаркта на одну треть.

Следующий интересный факт уже касается экономики в целом. Согласно той самой Gallup Inc. - далеко не последний авторитет в подобных вопросах - негативное или отстраненное отношение к работе стоит одной только только американской экономике от $250 до $300 _миллиардов_ в год только в потерянной производительности труда, а если начать считать происходящие из-за этого несчастные случаи, болезни, текучку, пропуски работы и просто воровство, то стоимость легко уходит за триллион долларов в год.

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

пятница, 25 сентября 2009 г.

Перешел на новую работу

Перешел на новую работу, теперь работаю в компании EvaPhone. Очень доволен - классный коллектив, потрясающая атмосфера стартапа, интересные задачи. Ближайшее время буду заниматься JavaScript, так что, думаю, в блоге появятся посты на тему ДжаваСкрипта.

пятница, 5 июня 2009 г.

Требования к Senior Java Developer

Нашел здесь требования к Java Senior Developer. Выкладываю их к себе в блог, как ориентир на будущее.

Senior Java Developer

Job Description:

Responsible for Java/J2EE/J2SE application development supporting business objectives while providing expertise in software development lifecycle phases from concept and design to testing. Analyzes, designs and builds component-based applications in a Web/internet delivery environment, including
- introduction of an application layer,
- modeling techniques,
- component and object-oriented design,
- complex algorithmic coding,
- systematic approaches to application integration.

Works on new and existing applications along with enhancements web sites, web applications, and infrastructure. Performs hands-on coding, mentors junior developers and assists in architecting web content solutions. Serves as liaison to internal customers, research groups and various business support areas. Expertise in server-side web presentation technologies.

Desirable Experience:

• A Bachelor’s degree in Computer Science, Mathematics or related discipline is required, or equivalent work experience and technical training.

• 5 or more years of Java experience managing application design, software development, maintenance and delivery with at least 2 years with application servers; e.g. Oracle 8i/9i/10g/11i Application Server; SQL Server; J2EE Application Server; IBM Websphere, Tomcat, or BEA Weblogic; Apache.
Related Articles

• Minimum of 3 years technical work experience in a team environment as a programmer.

• Strong experience with Web architecture and Web design and development tools and languages, e.g. JSP, JDBC, Java Servlets, Javabeans/EJBs, ASP, VB Script, SQL, Perl, UNIX, C++, CORBA, JavaScript, SOAP, XML/XSLT/FOP, HTML, Struts, ANT, CVS, CMP, WebLogic.

• Strong relational database experience (DB2, Sybase, SQL, Oracle 8i/9i/10g/11i). Strong background working in distributed Unix environments.

• Experience designing N-tiered applications, with multi-tier architecture and production Internet architectures.

• Strong experience developing and implementing highly complex technical solutions in a J2EE web environment.

• Superior organizational and time management skills.

• Excellent written and verbal communication skills

• Highly desirable:
- Rapid applications development or extreme programming experience
- Sun Certified Developer for Java 2 Platform
- Sun Certified Programmer for Java 2 Platform
- Sun Certified Developer for Java Web Services
- JavaScript Development Certified Professional
- Java Development Certified Professional

Постоянные читатели