понедельник, 18 мая 2015 г.

Java Date Format

Java Date Format

Просто справочный пост про форматы дат.
Конструктор по умолчанию использует паттерн времени и формат символов по умолчанию для текущей локализации. То есть, для русской локализации стандартным паттерном времени является паттерн "dd.MM.yy HH:mm".
Конструктор SimpleDateFormat(String pattern) принимает паттерн даты, в котором будет отдавать результат метод format(). В примере мы использовали паттерн "dd MMMM", который требует от format() вывести дату в следующем формате: "две цифры дня месяца" + "пробел" + "название месяца". В данном случае используется название месяца по умолчанию для текущей локализации, т.е., "Февраль".
Конструктор SimpleDateFormat("dd MMMM", myDateFormatSymbols ) аналогичен предыдущему за исключением того, что название месяца используется не по умолчанию, а те, которые возвращает переменная myDateFormatSymbols. В свою очередь, в переменной myDateFormatSymbols мы переопределили метод getMonths() чтобы он возвращал названия месяцев с прописной буквы и в родительном падеже.
Конструктор SimpleDateFormat("dd MMMM", Locale.ENGLISH) аналогичен конструктору SimpleDateFormat(String pattern), но использует заданную локализацию. В нашем случае это английская локализация Locale.ENGLISH.
Рассмотрим подробно параметры, принимаемые классом SimpleDateFormat в качестве паттерна даты.
СимволЧто означаетПример
Gэра (в английской локализации - AD и BC)н.э.
yгод (4-х значное число)2012
yyгод (последние 2 цифры)12
yyyyгод (4-х значное число)2012
Mномер месяца без лидирующих нулей2
MMномер месяца (с лидирующими нулями если номер месяца < 10)02
MMMчетырех буквенное сокращение месяца в русской локализации и трех буквенное - в английской (Feb)фев
MMMMполное название месяца (в английской локализации - February)Февраль
wнеделя в году без лидирующих нулей7
wwнеделя в году с лидирующими нулями07
Wнеделя в месяце без лидирующих нулей2
WWнеделя в месяце с лидирующим нулем (если это необходимо)02
Dдень в году38
dдень месяца без лидирующих нулей7
ddдень месяца с лидирующими нулями07
Fдень недели в месяце без лидирующих нулей1
FFдень недели в месяце с лидирующими нулями01
Eдень недели (сокращение)Вт
EEEEдень недели (полностью)вторник
aAM/PM указательAM
Hчасы в 24-часовом формате без лидирующих нулей6
HHчасы в 24-часовом формате с лидирующим нулем06
kколичество часов в 24-часовом формате18
Kколичество часов в 12-часовом формате6
hвремя в 12-часовом формате без лидирующих нулей6
hhвремя в 12-часовом формате с лидирующим нулем06
mминуты без лидирующих нулей32
mmминуты с лидирующим нулем32
sсекунды без лидирующих нулей11
ssсекунды с лидирующим нулем11
Sмиллисекунды109
zчасовой поясEET
Zчасовой пояс в формате RFC 822+0200
'символ экранирования для текста'Date='
''кавычка'o''clock'
Рассмотрим несколько примеров паттернов даты и времени, которые представлены в официальной документации. Русская локализация:
Паттерн даты и времениРезультат
"e;yyyy.MM.dd G 'at' HH:mm:ss z"e;2012.02.07 н.э. at 16:51:35 EET
"e;EEE, MMM d, ''yy"e;Вт, фев 7, '12
"e;h:mm a"e;4:51 PM
"e;hh 'o''clock' a, zzzz"e;04 o'clock PM, Eastern European Time
"e;K:mm a, z"e;4:51 PM, EET
"e;yyyyy.MMMMM.dd GGG hh:mm aaa"e;02012.Февраль.07 н.э. 04:51 PM
"e;EEE, d MMM yyyy HH:mm:ss Z"e;Вт, 7 фев 2012 16:51:35 +0200
"e;yyMMddHHmmssZ"e;120207165135+0200
Английская локализация:
Паттерн даты и времениРезультат
"e;yyyy.MM.dd G 'at' HH:mm:ss z"e;2012.02.07 AD at 16:55:57 EET
"e;EEE, MMM d, ''yy"e;Tue, Feb 7, '12
"e;h:mm a"e;4:55 PM
"e;hh 'o''clock' a, zzzz"e;04 o'clock PM, Eastern European Time
"e;K:mm a, z"e;4:55 PM, EET
"e;yyyyy.MMMMM.dd GGG hh:mm aaa"e;02012.February.07 AD 04:55 PM
"e;EEE, d MMM yyyy HH:mm:ss Z"e;Tue, 7 Feb 2012 16:55:57 +0200
"e;yyMMddHHmmssZ"e;120207165557+0200

вторник, 31 марта 2015 г.

Java Client WebSockets


Java Client WebSockets

Собственно решил сделать небольшую заметку про websocketы,а точнее реализация их клиентов на Java,серверной части тут не будет(она особо нам и не нужна для наших целей),
зато будут 2 реализации,кому какая больше нравится.
Итак,коротко что такое WebSocket:
WebSocket — протокол полнодуплексной связи поверх TCP-соединения, предназначенный для обмена сообщениями между браузером и веб-сервером в режиме реального времени.
Можно даже не до конца понимать определение из википедии,чтобы понять насколько широкие горизонты в разработке и тестировании открывает эта технология.
Сейчас напишем пару клиентских программ использующих вебсокет для соединения с сервером.
1й варинт.
Добавляем в pom.xml

 
        
            javax.websocket
            javax.websocket-client-api
            1.0
        
        
            org.glassfish.tyrus
            tyrus-client
            1.1
        
        
            org.glassfish.tyrus
            tyrus-container-grizzly
            1.1
        

И код самого клиента

 
@ClientEndpoint(configurator = WebSocketClientEndpoint.Configurator.class)
public class WebSocketClientEndpoint {
    private Logger logger = Logger.getLogger(WebSocketClientEndpoint.class);
    Session userSession = null;
    private MessageHandler messageHandler;

    public static class Configurator extends javax.websocket.ClientEndpointConfig.Configurator {
        static String cookiesConf;

        public static void addCookie(String cookies) {
            cookiesConf = cookies;
        }

        @Override
        public void beforeRequest(Map> headers) {
            headers.put("Cookie", Collections.singletonList(cookiesConf));
            super.beforeRequest(headers);
        }
    }

    public WebSocketClientEndpoint(String host, String port) {
        try {
            WebSocketContainer container = ContainerProvider.getWebSocketContainer();
            container.connectToServer(this, URI.create("ws://" + host + ":" + port));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @OnError
    public void onError(Throwable t) {
        t.printStackTrace();
    }

    /**
     * Callback hook for Connection open events.
     *
     * @param userSession the userSession which is opened.
     */
    @OnOpen
    public void onOpen(Session userSession) {
        logger.info("Opening WS");
        this.userSession = userSession;

    }

    /**
     * Callback hook for Connection close events.
     *
     * @param userSession the userSession which is getting closed.
     * @param reason      the reason for connection close
     */
    @OnClose
    public void onClose(Session userSession, CloseReason reason) {
        logger.info("Closing WS");
        this.userSession = null;
    }

    /**
     * Callback hook for Message Events. This method will be invoked when a client send a message.
     *
     * @param message The text message
     */
    @OnMessage
    public void onMessage(String message) {
        if (this.messageHandler != null) this.messageHandler.handleMessage(message);
    }

    /**
     * register message handler
     */
    public WebSocketClientEndpoint addMessageHandler(MessageHandler msgHandler) {
        this.messageHandler = msgHandler;
        return this;
    }

    /**
     * Send a message.
     *
     * @param message
     */
    public WebSocketClientEndpoint sendMessage(String message) {
        this.userSession.getAsyncRemote().sendText(message);
        if (this.messageHandler != null) this.messageHandler.handleMessage(message);
        return this;
    }


    public interface MessageHandler {
        void handleMessage(String message);
    }
}

И пользуемся им как то так:

 
     WebsocketClientEndpoint clientEndPoint = new WebsocketClientEndpoint(new URI("ws://test.dev:8080"));
            // add listener
            clientEndPoint.addMessageHandler(message -> System.out.println(message));
            // send message to websocket
            clientEndPoint.sendMessage("{'event':'Hello world!'}");


Вроде удобно,просто и быстро.Но мне понадобилась поддержка cookie и  в данной реализации это создает определенные сложности(вроде статического класса конфигуратора),так что я использовал 2й вариант на jetty.
Добавляем в pom.xml


 

        
            org.eclipse.jetty.aggregate
            jetty-all-server
            8.1.16.v20140903
        
        
            org.eclipse.jetty.websocket
            websocket-client
            9.2.10.v20150310
        

И код самого клиента:

 
public class ClientWebSocket {
    private Logger logger = Logger.getLogger(ClientWebSocket.class);
    private WebSocket.Connection connection;
    private WebSocketClient client;
    private WebSocketClientFactory factory;

    ClientWebSocket() {
        factory = new WebSocketClientFactory();
        try {
            factory.start();
        } catch (Exception e) {
            logger.info("Factory start problem");
        }
        client = new WebSocketClient(factory);
    }

    public ClientWebSocket open(String uri) {
        try {
            Future connectionFuture = client.open(URI.create(uri), new WebSocket.OnTextMessage() {
                @Override
                public void onMessage(String s) {
                    logger.info(s);
                }

                @Override
                public void onOpen(Connection connection) {
                    logger.info("Opening WS");
                }

                @Override
                public void onClose(int i, String s) {
                    logger.info("Closing WS");
                }
            });
            try {
                this.connection = connectionFuture.get();
            } catch (InterruptedException | ExecutionException e) {
                logger.info("Cant get connection ws");
            }
        } catch (IOException e) {
            logger.info("IO exception with open ws");
        }
        return this;

    }

    public ClientWebSocket addCookies(String name, String value) {
        client.getCookies().put(name, value);
        return this;
    }

    public ClientWebSocket sendMessage(String mess) {
        try {
            connection.sendMessage(mess);
        } catch (Exception e) {
            logger.info("Plz open the connection");
        }
        return this;
    }

    public ClientWebSocket closeConnection() {
        try {
            connection.close();
            factory.stop();
        } catch (Exception e) {
            logger.info("Close connection error");
        }
        return this;
    }
}

И используем его как то так:

 
 String uri = "ws://test.dev:8080";
        ClientWebSocket client = new ClientWebSocket();
        client.addCookies("_user_id", "111111").open(uri).sendMessage("{'event':'Hello world!'}").closeConnection();

Вот так все просто.

четверг, 15 января 2015 г.

Java Annotations

Java Annotations

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

Так давайте как то выделим такие тесты в отчете и при падении известных нам тестов в сьюте будем выводить ссылку на баг.

Все вроде как просто и делается так же просто.
Делаем простенькую аннотацию

 
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface IsKnownBug {
    public String getBugUrl();

    public String getBugDescription() default "";
}

Теперь нам нужно ее отслеживать,можно это сделать кучей способов и вот один из них


 
   @Override
    public void afterInvocation(IInvokedMethod method, ITestResult testResult) {
            if (method.getTestMethod().getMethod().getAnnotation(IsKnownBug.class) != null && testResult.getStatus() == ITestResult.FAILURE) {
                makeScreenshot(testResult.getName());
                IsKnownBug clazz = testResult.getMethod().getMethod().getAnnotation(IsKnownBug.class);
                Assert.fail(clazz.getBugUrl() + " " + clazz.getBugDescription());
            }
            }
        }

Сам тест помеченный аннотацией будет выглядеть как то так:


 
  @IsKnownBug(getBugUrl = "http://jira.test.ru/browse/TEST-7583", getBugDescription = "IMORTANT BUG")
    @Test(description = "check elements with online after filter on the main page")
    public void checkElementsWithOnlineAfterFilter(Class page) {
    }

Ну и в отчете это будет выглядеть как то так


Вот и все.Всем спасибо.

пятница, 29 августа 2014 г.

Load testing with Amazon

Использование EC2 Amazon для нагрузочного тестирования

Думаю, что тут все просто.Не всегда нам хватает своих машин или своей ширины канала для нагрузочного тестирования.
А быстро нам все это предоставить не всегда возможно,но есть выход что с этим делать.
Можно воспользоваться EC2 Amazon.
Сервис который предоставит нам до 10 микро инстансов,на удобной нам системе и бесплатно(правда только первый год,но нам этого хватит)

В общем то все это сделать можно достаточно просто,но не совсем,постараюсь рассказать.
1.Создаем нужный нам instance машины.
2.Начинаем предварительную настройку машины.

Важно!-Не нужно заходить на машину и настраивать iptables,как делал сначала я.Все это настраиваться в UI Instance в категории Security Groups.

3.Настраиваем доступы следующим образом


4.После этого мы уже почти закончили)
Сетапим Jmeter и запускаем на машинах jmeter-server
Запускаем примерно вот так

jmeter-server -Dserver.rmi.localport=2048 -Djava.rmi.server.hostname=`curl -s http://169.254.169.254/latest/meta-data/public-ipv4`

На всякий случай объясню,что мы тут делаем.
Мы биндим RMI на 2048 порт и запускаем сервер с публичным IP который нам предоставил EC2

5.Нам понадобится ssh туннели,кто не в курсе как это и что это лезем сюда.

ssh -R11099:localhost:11099 ...(user@ip)

ssh -i yourkey.pem -R 11099:localhost:11099 ec2-user@54.213.155.162

6.На основной машине запускаем Jmeter следующим образом

jmeter -Dclient.rmi.localport=11099 -Djava.rmi.server.hostname=localhost 

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

Кстати скопировать на инстанс проще всего как то так 

rsync -azvv --progress -e "ssh -i pathtopem.pem" target_folder ec2-user@52.88.37.176:destination_folder

Вот собственно и все.
Всем спасибо.







пятница, 27 июня 2014 г.

JDK Linux

JDK Linux

Вот уж точно статья только для себя,потому что постоянно с этим что то не так,но мб и еще кому пригодится.
Собственно. Если кто не в курсе, то в какой-то момент компаниякоторуюнельзяназывать изменила лицензионное соглашение для JDK так, что её стало невозможно распространять через линуксячьи репозитории.
OpenJDK, который остался в репозиториях — полный шлак и не умеет даже запускать KVM-ные апплеты. Очень многие.
Тем временем jdk делает огромные шаги, вышла уже 8я версия (шустрее, выше, сильнее, а главное, что нет проблем с доступом к ipmi/ip-kvm вообще никаких).
Вот только процесс установки теперь для убунтоводов несколько нетривиален.

По-хорошему нужно пойти сюда, и ткнуть «download» под нужной версией. 
Когда мы получим файл — можно наконец-то распрощаться с оракловым говносайтом и спокойно идти в консольку.
У меня получился файл jdk-7u4-linux-x64.tar.gz
user@host:~$ tar -xvf jdk-7u4-linux-x64.tar.gz
Положим это отродие в правильное с его точки зрения место:
root@host:~# mv jdk1.7.0_04 /usr/lib/jvm/
Создадим переменную, чтобы мануал остался универсальным для любых версий (потом всё следует делать в том же терминале):
root@host:~# jdir=jdk1.7.0_04
# здесь после равно нужно указать название каталога, которому мы делали mv
Теперь создадим правильные симлинки внутри системы:
root@host:~# update-alternatives --install /usr/bin/javac javac /usr/lib/jvm/$jdir/bin/javac 1
root@host:~# update-alternatives --install /usr/bin/java java /usr/lib/jvm/$jdir/bin/java 1
root@host:~# update-alternatives --install /usr/bin/javaws javaws /usr/lib/jvm/$jdir/bin/javaws 1
root@host:~# update-alternatives --install /usr/bin/jar jar /usr/lib/jvm/$jdir/bin/jar 1
Теперь самое время убедить нашу убунту в том, что следует использовать именно 7ю jdk, которую мы только что «установили». Если других версий jdk вы не ставили — то вам просто для успокоения совести следует ввести следующие 3 команды. Если ставили — то нам зададут всякие глупые вопросы. На них придется ответить:
root@host:~# update-alternatives --config javac
There are 2 choices for the alternative javac (providing /usr/bin/javac).

Selection Path Priority Status
------------------------------------------------------------
* 0 /usr/lib/jvm/java-7-openjdk-amd64/bin/javac 1051 auto mode
1 /usr/lib/jvm/java-7-openjdk-amd64/bin/javac 1051 manual mode
2 /usr/lib/jvm/jdk1.7.0_04/bin/javac 1 manual mode

Press enter to keep the current choice[*], or type selection number: 2
root@host:~# update-alternatives --config java
There are 2 choices for the alternative java (providing /usr/bin/java).

Selection Path Priority Status
------------------------------------------------------------
* 0 /usr/lib/jvm/java-7-openjdk-amd64/jre/bin/java 1051 auto mode
1 /usr/lib/jvm/java-7-openjdk-amd64/jre/bin/java 1051 manual mode
2 /usr/lib/jvm/jdk1.7.0_04/bin/java 1 manual mode

Press enter to keep the current choice[*], or type selection number: 2
root@host:~# update-alternatives --config javaws
There is only one alternative in link group javaws: /usr/lib/jvm/jdk1.7.0_04/bin/javaws
Nothing to configure.
root@host:~# update-alternatives --config jar
...
Теперь проверим, что мы всё настроили верно:
user@host:~$ ls -la /etc/alternatives/{java,javac,javaws,jar}
lrwxrwxrwx 1 root root 33 May 23 01:40 /etc/alternatives/java -> /usr/lib/jvm/jdk1.7.0_04/bin/java
lrwxrwxrwx 1 root root 34 May 23 01:39 /etc/alternatives/javac -> /usr/lib/jvm/jdk1.7.0_04/bin/javac
lrwxrwxrwx 1 root root 35 May 23 00:29 /etc/alternatives/javaws -> /usr/lib/jvm/jdk1.7.0_04/bin/javaws
...
user@host:~$ java -version
java version "1.7.0_04"
Java(TM) SE Runtime Environment (build 1.7.0_04-b20)
Java HotSpot(TM) 64-Bit Server VM (build 23.0-b21, mixed mode)
Ну и осталась мелочь — рассказать нашим браузерам, что у нас есть java-плагин к ним (это актуально почти для всех браузеров, для FF и Chrome/Iron/Chromium — точно):
root@host:~# username=set_your_username_here; su ${username} -c "mkdir ~${username}/.mozilla/plugins"; rm /home/${username}/.mozilla/plugins/libnpjp2.so; su ${username} -c "ln -s /usr/lib/jvm/$jdir/jre/lib/amd64/libnpjp2.so ~${username}/.mozilla/plugins/"
Проверить, что оно заработало можно здесь.

Вот и все.

Java Simple WebService

Java Simple WebService

Решил для себя описать(чтобы не забыть и все такое) создание простейшего вебсервиса на Java.
С использованием технологии JAX-WS.Будет 2 примера,каждый мне в чем то нравится.

Для начала,что такое JAX-WS?
JAX-WS - это технология, разработанная для упрощения создания Web-сервисов и клиентов Web-сервисов на языке Java. Она предоставляет полный стек Web-сервисов, облегчающий разработку и развертывание Web-сервисов. JAX-WS поддерживает WS-I Basic Profile 1.1. Это гарантирует, что Web-сервисы, разработанные с использованием стека JAX-WS, могут потребляться любыми клиентами, разработанными на любом языке программирования и удовлетворяющими стандарту WS-I Basic Profile. 
Более того, JAX-WS ускоряет разработку Web-сервисов, предоставляя библиотеку аннотаций для преобразования POJO-классов (plain old Java object – традиционные Java-объекты) в Web-сервисы. Она также определяет детализированное отображение сервисов, определенных на языке WSDL (Web Services Description Language), в Java-классы, реализующие эти сервисы. Все сложные типы, определенные в WSDL, отображаются в Java-классы согласно отображению, определенному спецификацией JAXB. JAX-WS ранее поставлялась с платформой Java Platform, Enterprise Edition (Java EE) 5. Спецификация JAX-WS 2.0 разрабатывается под эгидой JSR 224 Java Community Process (JCP).
Для начала у нас будет просто WebService(как в большинстве примерах)


 
@WebService
public class HelloService {
    private String message = "Hello, ";

    @WebMethod//единственный вебметод нашего сервиса
    public String sayHello(String name) {
        return message + name + ".";
    }

    public static void main(String[] args) {
        Endpoint.publish("http://localhost:8080/WS/Greeting",new HelloService()); //паблишим сервис по указанному урлу
    }
}
Запусаем main и наш сервис запаблишится на том урле,который мы указали.
Можно перейти на http://localhost:8080/WS/Greeting?wsdl ,чтобы проверить его доступность.
Дальше нам нужен клиент для работы с сервисом и отладки.

1й способ.

Выполнить из папки проекта команду
wsimport -keep -p com.client  http://localhost:8080/WS/Greeting?wsdl
Параметр -keep указывает, что сгенерированные файлы сохраняются, а параметр -p указывает название пакета, в который должны генерироваться артефакты.  http://localhost:8080/WS/Greeting?wsdl указывает месторасположение WSDL-файла. 

wsimport поставляется вместе с jdk,так что переживать по её поводу не нужно.

После этого у нас будет несколько сгенеренных классов для работы с сервисом и клиент будет выглядеть примерно так:

 
public class Client {
    @WebServiceRef(wsdlLocation = "http://localhost:8080/WS/Greeting?wsdl")
    HelloServiceService service=new HelloServiceService();

    public static void main(String[] args) {
        try {
            String response = service.getHelloServicePort().sayHello("Robert");
            System.out.println(response);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
В ответ вы должны получить "Hello Robert."

Способ 2

2й способ без генерации вспомогаемых классов утилитой wsimport.
Нам понадобится интерфейс нашего веб сервиса.

 
@WebService
public interface IService {
   @WebMethod
   public String sayHello(String name);
}
Наш сервис должен реализовывать этот интерфейс,как вы догадались

 
@WebService(endpointInterface = "com.main.IService")
public class HelloService implements IService{
    
    private String message = "Hello, ";
    @WebMethod
    public String sayHello(String name) {
        return message + name + ".";
    }

    public static void main(String[] args) {
        Endpoint.publish("http://localhost:8080/ws/Greeting",new HelloService());
    }
}

И пишем сам клиент.

 
public class Client {
    public static void main(String[] args) throws MalformedURLException {
        URL url = new URL("http://localhost:8080/ws/Greeting?wsdl");
        QName qname = new QName("http://main.com/", "HelloServiceService");
        Service service = Service.create(url, qname);
        IService hello = service.getPort(IService.class);
        System.out.println(hello.sayHello("Cool guy"));
    }
}

Ответ должен быть "Hello,Cool guy".

Вот и все,всем спасибо.