понедельник, 9 ноября 2015 г.

JAVA RESTful Service

JAVA RESTful Service


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

Поехали.

Создадим обычный maven проект и добавим следующие зависимости

 
  
        com.sun.jersey
        jersey-server
        1.19
    


Этого достаточно чтобы поднять простой сервис с  Jersey и Jax-RS.
Выглядеть он будет достаточно тривиально,примерно следующим образом:


 
@Path("/")
public class RestService {




    @GET//метод обращения
    @Path("/helloworld")//относительный путь
    @Produces(MediaType.TEXT_PLAIN)//Мы можем указать представление типа MIME для ресурса, используя Produces аннотацию
    public String getClichedMessage() {
        return "Hello World";
    }

    @GET
    @Path("/verify")
    @Produces(MediaType.TEXT_PLAIN)
    public Response verifyRESTService(InputStream incomingData) {
        String result = "Thats ok";
        return Response.status(200).entity(result).build();
    }


    @POST
    @Path("/post")
    @Consumes(MediaType.APPLICATION_JSON)
    public Response post(String incomingData) {
        JSONObject jsonObject;
        try {
            jsonObject = new JSONObject(incomingData);
        } catch (JSONException ex) {
            return Response.status(500).entity("Error while parsing").build();
        }

        System.out.println("Data Received: " + jsonObject.toString());
        return Response.status(200).entity(jsonObject.toString()).build();
    }


    @POST
    @Path("/paramPost")
    @Consumes(MediaType.APPLICATION_JSON)
    public Response postWithParam(@FormParam("data")String incomingData) {
        JSONObject jsonObject;
        try {
            jsonObject = new JSONObject(incomingData);
        } catch (JSONException ex) {
            return Response.status(500).entity("Error while parsing").build();
        }

        System.out.println("Data Received: " + jsonObject.toString());
        return Response.status(200).entity(jsonObject.toString()).build();
    }

    public static void main(String[] args) throws IOException {
        HttpServer server = HttpServerFactory.create("http://localhost:9998/");
        server.start();
        System.out.println("Сервер запущен");
    }
}

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

Чтобы создать клиент для проверки нашего сервиса есть 2 варианта.

1.С использованием Apache Http Client


 
  public static void main(String[] argv) throws IOException {
        String jsonObject="{\n" +
                "    \"tutorials\": {\n" +
                "        \"id\": \"Apt\",\n" +
                "        \"topic\": \"REST Service\",\n" +
                "        \"description\": \"This is REST Service\"\n" +
                "    }\n" +
                "}";
        HttpClient httpClient =  HttpClientBuilder.create().build();
        HttpPost postRequest =  new HttpPost(new URIBuilder().setPath("http://localhost:9998/post").toString());
        StringEntity input = new StringEntity(jsonObject);
        input.setContentType("application/json");
        postRequest.setEntity(input);
        HttpResponse response1 = httpClient.execute(postRequest);
        System.out.println(new BasicResponseHandler().handleResponse(response1));


        HttpPost request = new HttpPost("http://localhost:9998/paramPost");
        request.setEntity(new UrlEncodedFormEntity(Collections.singletonList(new BasicNameValuePair("data", jsonObject))));
        HttpResponse response = httpClient.execute(postRequest);
        System.out.println(new BasicResponseHandler().handleResponse(response));

    }


2.Используя Jersey клиент.
Добавим в зависимости

 
  
        com.sun.jersey
        jersey-client
        1.19
    

    
        com.sun.jersey
        jersey-json
        1.19
    


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

 
public class ClientJersey {

    public static void main(String[] args) {
        try {
            String jsonObject="{\n" +
                    "    \"tutorials\": {\n" +
                    "        \"id\": \"Apt\",\n" +
                    "        \"topic\": \"REST Service\",\n" +
                    "        \"description\": \"This is REST Service\"\n" +
                    "    }\n" +
                    "}";
            ClientConfig clientConfig = new DefaultClientConfig();
            clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
            Client clientJersey = Client.create(clientConfig);
            WebResource webResource = clientJersey.resource("http://localhost:9998/post");
            ClientResponse response = webResource.accept("application/json").type("application/json").post(ClientResponse.class, jsonObject);
            if (response.getStatus() != 200) {
                throw new RuntimeException("Failed : HTTP error code : "
                        + response.getStatus());
            }
            String output = response.getEntity(String.class);
            System.out.println("Server response .... \n");
            System.out.println(output);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

Вот собственно и все,вот так просто.

четверг, 1 октября 2015 г.

Appium in Action

Установка Appium и тестирование мобильных приложений.


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

Ставим NodeJs,способов куча,так что это просто.

После чего надо поставить все остальное
Запустите следующую команду в окне терминала :
Шаг 1 : Затем в окне терминала выполнить следующие команды:
npm install -g grunt-cli
Шаг 2 : Затем в окне терминала выполнить следующие команды:
npm install -g appium
Шаг 3 : Затем в окне терминала выполнить следующие команды:
npm install wd
Шаг 4 : Затем в окне терминала выполнить следующие команды для запуска сервера Appium :
appium &

Есть вероятность,что пакеты не ставятся на unix системах без sudo,а ставить с ним нам нельзя((
тогда делаем так 

 
$sudo npm uninstall -g appium 
$sudo chmod -R a+w /usr/local 
$npm install -g appium

И нужно обязательно добавить путь к вашему Andoid SDK

 
export ANDROID_HOME=pathtosdk

Теперь в вашем проекте с тестами,добавляем в maven зависимости следующее


 
  
            io.appium
            java-client
            version
        

Ну и примерный запуск самого простого теста как то так :


 
public class TestAndroid {

    private AppiumDriver driver;
    private static AppiumDriverLocalService service;

    @BeforeClass
    public static void beforeClass() throws Exception{
        service = AppiumDriverLocalService.buildDefaultService();
        service.start();
    }

    @Before
    public void setUp() throws Exception {
        if (service == null || !service.isRunning())
            throw new RuntimeException("An appium server node is not started!");

        File appDir = new File("pathToapk");
        File app = new File(appDir, "app-debug.apk");
        DesiredCapabilities capabilities = new DesiredCapabilities();
        capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Android Emulator");
        capabilities.setCapability(MobileCapabilityType.APP, app.getAbsolutePath());
        driver = new AndroidDriver(service.getUrl(), capabilities);
    }

    @After
    public void tearDown() throws Exception {
        driver.quit();
    }

    @Test
    public void findElementsTest() {
        List elements = driver.findElementsById("button");
        assertTrue(elements.size() > 0);
    }

}

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

понедельник, 3 августа 2015 г.

Многопоточность Java

CountDownLatch и Semaphore

В общем то,достаточно сжатая информация об удобных вещах в пакете java.util.concurrent,
а точнее о паре вещей оттуда.

CountDownLatch

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


 
CountDownLatch latch = new CountDownLatch(3);//по количеству потоков которых мы будем ждать
И 2 основных метода  countDown и await.
Метод await заставляет текущий поток ожидать,пока счетчик защелки не станет равен 0.
Метод countDown декрементит счетчик заданный в конструкторе и как только он дойдет до 0,потоки продолжат выполнение.

Вот пример со скачками(пример не мой,я только напихал больше комментариев по коду,ну и сократил лишнее)


 
class Race
{
    private Random rand = new Random();
    private int distance = 50;
    private List horses = Arrays.asList("Vanek","Robert","Polson","Rak");
    public void run() throws InterruptedException
    {
        System.out.println("And the horses are stepping up to the gate...");
        final CountDownLatch start = new CountDownLatch(1);//защелка для одновременного старта для всех коней,1-тк защелка для основного потока выполнения
        start.await();
        final CountDownLatch finish = new CountDownLatch(horses.size());//защелка для финиша, а здесь по количеству лошадей
        final List places = Collections.synchronizedList(new ArrayList<>());
        horses.forEach(horse -> new Thread(() -> {
            try {
                System.out.println(horse + " stepping up to the gate...");
                start.await(); // Блокируем поток,чтобы не было не одного фальстарта у наших коней
                int traveled = 0;//пройденный путь для коня
                while (traveled < distance) {
                    // каждые 0-2 секунды лошадь проходит дистанцию 0-14 пунктов
                    Thread.sleep(rand.nextInt(3) * 1000);
                    traveled += rand.nextInt(15);
                    System.out.println(horse + " advanced to " + traveled + "!");
                }
                finish.countDown();//уменьшение счетчика защелки,тк мы будем ждать именно этого момента в самой программе и когда последний конь финиширует исполнение завершится
                System.out.println(horse + " crossed the finish!");
                places.add(horse);
            } catch (InterruptedException intEx) {
                System.out.println("ABORTING RACE!!!");
                intEx.printStackTrace();
            }
        }).start());
        System.out.println("And... they're off!");
        start.countDown();//снимаем нашу защелку для старта
        finish.await();//ожидаем финиша наших скакунов
        System.out.println("And we have our winners!");
        System.out.println(places.get(0) + " took the gold...");
        System.out.println(places.get(1) + " got the silver...");
        System.out.println("and " + places.get(2) + " took home the bronze.");
    }

    public static void main(String[] args) throws InterruptedException {
        new Race().run();
    }
}

Вот как то так.

Теперь про класс Semaphore.

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

 
Semaphore available = new Semaphore(3);//по количеству потоков которые будут активны

И 2 основных метода acquire() и release().
acquire()-Уменьшает счетчик доступных потоков(который мы задали в конструкторе) на 1.
release()-Соответственно освобождает его и увеличивает счетчик.

Небольшой пример

 
 public static void main(String[] args)
    {
        Runnable limitedCall = new Runnable() {
            final Random rand = new Random();
            final Semaphore available = new Semaphore(3);
            int count = 0;
            public void run()
            {
                int time = rand.nextInt(15);
                int num = count++;
                try
                {
                    available.acquire();//задействуем поток
                    System.out.println("Executing " +
                            "long-running action for " +time +
                            " seconds... #" + num);

                    Thread.sleep(time * 1000);
                    System.out.println("Done with #" + num + "!");
                    available.release();//после его работы освобождаем 
                }
                catch (InterruptedException intEx)
                {
                    intEx.printStackTrace();
                }
            }
        };
        for (int i=0; i<10 data-blogger-escaped-i="" data-blogger-escaped-limitedcall="" data-blogger-escaped-new="" data-blogger-escaped-pre="" data-blogger-escaped-start="" data-blogger-escaped-thread="">
Создаем 10 потоков(можно убедиться выполнив команду jstack),однако только 3 из них активны.Как только один их потоков освобождает семафор,другой занимает его место.
Вот и все.

понедельник, 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