[{"data":1,"prerenderedAt":13428},["ShallowReactive",2],{"navigation":3,"blog":406,"blog-posts":419},[4,8,39,52,264,310,319,380,397],{"title":5,"path":6,"stem":7},"Notes","\u002Fnotes","1.notes\u002Findex",{"title":9,"path":10,"stem":11,"children":12,"page":30},"Architecture","\u002Fnotes\u002Farchitecture","1.notes\u002Farchitecture",[13,17,31,35],{"title":14,"path":15,"stem":16},"API Management","\u002Fnotes\u002Farchitecture\u002Fapi-management","1.notes\u002Farchitecture\u002Fapi-management",{"title":18,"path":19,"stem":20,"children":21,"page":30},"Data","\u002Fnotes\u002Farchitecture\u002Fdata","1.notes\u002Farchitecture\u002Fdata",[22,26],{"title":23,"path":24,"stem":25},"ERD","\u002Fnotes\u002Farchitecture\u002Fdata\u002Ferd","1.notes\u002Farchitecture\u002Fdata\u002Ferd",{"title":27,"path":28,"stem":29},"SCWD","\u002Fnotes\u002Farchitecture\u002Fdata\u002Fscwd","1.notes\u002Farchitecture\u002Fdata\u002Fscwd",false,{"title":32,"path":33,"stem":34},"Microservices","\u002Fnotes\u002Farchitecture\u002Fmicroservices","1.notes\u002Farchitecture\u002Fmicroservices",{"title":36,"path":37,"stem":38},"OAuth","\u002Fnotes\u002Farchitecture\u002Foauth","1.notes\u002Farchitecture\u002Foauth",{"title":40,"path":41,"stem":42,"children":43,"page":30},"Archive","\u002Fnotes\u002Farchive","1.notes\u002Farchive",[44,48],{"title":45,"path":46,"stem":47},"Google Web Toolkit","\u002Fnotes\u002Farchive\u002Fgwt","1.notes\u002Farchive\u002Fgwt",{"title":49,"path":50,"stem":51},"Jekyll","\u002Fnotes\u002Farchive\u002Fjekyll","1.notes\u002Farchive\u002Fjekyll",{"title":53,"path":54,"stem":55,"children":56,"page":30},"Development","\u002Fnotes\u002Fdevelopment","1.notes\u002Fdevelopment",[57,74,112,149,226,239,260],{"title":58,"icon":30,"path":59,"stem":60,"children":61,"page":30},"IDE","\u002Fnotes\u002Fdevelopment\u002Fide","1.notes\u002Fdevelopment\u002FIDE",[62,66,70],{"title":63,"path":64,"stem":65},"Jetbrains IDE","\u002Fnotes\u002Fdevelopment\u002Fide\u002Fjetbrains","1.notes\u002Fdevelopment\u002FIDE\u002Fjetbrains",{"title":67,"path":68,"stem":69},"NVIM","\u002Fnotes\u002Fdevelopment\u002Fide\u002Fnvim","1.notes\u002Fdevelopment\u002FIDE\u002Fnvim",{"title":71,"path":72,"stem":73},"tmux","\u002Fnotes\u002Fdevelopment\u002Fide\u002Ftmux","1.notes\u002Fdevelopment\u002FIDE\u002Ftmux",{"title":75,"path":76,"stem":77,"children":78,"page":30},"Algo","\u002Fnotes\u002Fdevelopment\u002Falgo","1.notes\u002Fdevelopment\u002Falgo",[79,83,87,91,95],{"title":80,"path":81,"stem":82},"Algorithms","\u002Fnotes\u002Fdevelopment\u002Falgo\u002Falgorithms","1.notes\u002Fdevelopment\u002Falgo\u002Falgorithms",{"title":84,"path":85,"stem":86},"Data Structures","\u002Fnotes\u002Fdevelopment\u002Falgo\u002Fdata_structures","1.notes\u002Fdevelopment\u002Falgo\u002Fdata_structures",{"title":88,"path":89,"stem":90},"Kata","\u002Fnotes\u002Fdevelopment\u002Falgo\u002Fkata","1.notes\u002Fdevelopment\u002Falgo\u002Fkata",{"title":92,"path":93,"stem":94},"O-notation","\u002Fnotes\u002Fdevelopment\u002Falgo\u002Fo-notation","1.notes\u002Fdevelopment\u002Falgo\u002Fo-notation",{"title":96,"path":97,"stem":98,"children":99,"page":30},"Sorting","\u002Fnotes\u002Fdevelopment\u002Falgo\u002Fsorting","1.notes\u002Fdevelopment\u002Falgo\u002Fsorting",[100,104,108],{"title":101,"path":102,"stem":103},"Buble Sort","\u002Fnotes\u002Fdevelopment\u002Falgo\u002Fsorting\u002Fbublesort","1.notes\u002Fdevelopment\u002Falgo\u002Fsorting\u002Fbublesort",{"title":105,"path":106,"stem":107},"Merge Sort","\u002Fnotes\u002Fdevelopment\u002Falgo\u002Fsorting\u002Fmergesort","1.notes\u002Fdevelopment\u002Falgo\u002Fsorting\u002Fmergesort",{"title":109,"path":110,"stem":111},"Quicksort","\u002Fnotes\u002Fdevelopment\u002Falgo\u002Fsorting\u002Fquicksort","1.notes\u002Fdevelopment\u002Falgo\u002Fsorting\u002Fquicksort",{"title":113,"path":114,"stem":115,"children":116,"page":30},"DataStructures","\u002Fnotes\u002Fdevelopment\u002Fdata_structures","1.notes\u002Fdevelopment\u002Fdata_structures",[117,121,125,129,133,137,141,145],{"title":118,"path":119,"stem":120},"ArrayList","\u002Fnotes\u002Fdevelopment\u002Fdata_structures\u002Farray_list","1.notes\u002Fdevelopment\u002Fdata_structures\u002Farray_list",{"title":122,"path":123,"stem":124},"Arrays","\u002Fnotes\u002Fdevelopment\u002Fdata_structures\u002Farrays","1.notes\u002Fdevelopment\u002Fdata_structures\u002Farrays",{"title":126,"path":127,"stem":128},"HashSet","\u002Fnotes\u002Fdevelopment\u002Fdata_structures\u002Fhash_set","1.notes\u002Fdevelopment\u002Fdata_structures\u002Fhash_set",{"title":130,"path":131,"stem":132},"LinkedList","\u002Fnotes\u002Fdevelopment\u002Fdata_structures\u002Flinked_list","1.notes\u002Fdevelopment\u002Fdata_structures\u002Flinked_list",{"title":134,"path":135,"stem":136},"PriorityQueue","\u002Fnotes\u002Fdevelopment\u002Fdata_structures\u002Fpriority_queue","1.notes\u002Fdevelopment\u002Fdata_structures\u002Fpriority_queue",{"title":138,"path":139,"stem":140},"Stack","\u002Fnotes\u002Fdevelopment\u002Fdata_structures\u002Fstack","1.notes\u002Fdevelopment\u002Fdata_structures\u002Fstack",{"title":142,"path":143,"stem":144},"TreeSet","\u002Fnotes\u002Fdevelopment\u002Fdata_structures\u002Ftree_set","1.notes\u002Fdevelopment\u002Fdata_structures\u002Ftree_set",{"title":146,"path":147,"stem":148},"Vector","\u002Fnotes\u002Fdevelopment\u002Fdata_structures\u002Fvector","1.notes\u002Fdevelopment\u002Fdata_structures\u002Fvector",{"title":150,"path":151,"stem":152,"children":153,"page":30},"Java","\u002Fnotes\u002Fdevelopment\u002Fjava","1.notes\u002Fdevelopment\u002Fjava",[154,158,162,166,170,174,178,182,186,190,194,198,202,206,210,214,218,222],{"title":155,"path":156,"stem":157},"Bit Operations","\u002Fnotes\u002Fdevelopment\u002Fjava\u002Fbit-operations","1.notes\u002Fdevelopment\u002Fjava\u002Fbit-operations",{"title":159,"path":160,"stem":161},"Cheatsheet","\u002Fnotes\u002Fdevelopment\u002Fjava\u002Fcheatsheet","1.notes\u002Fdevelopment\u002Fjava\u002Fcheatsheet",{"title":163,"path":164,"stem":165},"Clean Code","\u002Fnotes\u002Fdevelopment\u002Fjava\u002Fclean-code-presentation","1.notes\u002Fdevelopment\u002Fjava\u002Fclean-code-presentation",{"title":167,"path":168,"stem":169},"Java Datasource","\u002Fnotes\u002Fdevelopment\u002Fjava\u002Fdata-sources","1.notes\u002Fdevelopment\u002Fjava\u002Fdata-sources",{"title":171,"path":172,"stem":173},"Dependency Injection","\u002Fnotes\u002Fdevelopment\u002Fjava\u002Fdependency-injection-presentation","1.notes\u002Fdevelopment\u002Fjava\u002Fdependency-injection-presentation",{"title":175,"path":176,"stem":177},"Java SE","\u002Fnotes\u002Fdevelopment\u002Fjava\u002Fjava-standard-edition","1.notes\u002Fdevelopment\u002Fjava\u002Fjava-standard-edition",{"title":179,"path":180,"stem":181},"Java Memory Model","\u002Fnotes\u002Fdevelopment\u002Fjava\u002Fjmm","1.notes\u002Fdevelopment\u002Fjava\u002Fjmm",{"title":183,"path":184,"stem":185},"JPA","\u002Fnotes\u002Fdevelopment\u002Fjava\u002Fjpa","1.notes\u002Fdevelopment\u002Fjava\u002Fjpa",{"title":187,"path":188,"stem":189},"Keywords","\u002Fnotes\u002Fdevelopment\u002Fjava\u002Fkeywords","1.notes\u002Fdevelopment\u002Fjava\u002Fkeywords",{"title":191,"path":192,"stem":193},"Maven","\u002Fnotes\u002Fdevelopment\u002Fjava\u002Fmaven","1.notes\u002Fdevelopment\u002Fjava\u002Fmaven",{"title":195,"path":196,"stem":197},"Spring AOP","\u002Fnotes\u002Fdevelopment\u002Fjava\u002Fspring-aop-presentation","1.notes\u002Fdevelopment\u002Fjava\u002Fspring-aop-presentation",{"title":199,"path":200,"stem":201},"Spring Boot","\u002Fnotes\u002Fdevelopment\u002Fjava\u002Fspring-boot","1.notes\u002Fdevelopment\u002Fjava\u002Fspring-boot",{"title":203,"path":204,"stem":205},"Spring Core","\u002Fnotes\u002Fdevelopment\u002Fjava\u002Fspring-core-presentation","1.notes\u002Fdevelopment\u002Fjava\u002Fspring-core-presentation",{"title":207,"path":208,"stem":209},"Spring Data","\u002Fnotes\u002Fdevelopment\u002Fjava\u002Fspring-data","1.notes\u002Fdevelopment\u002Fjava\u002Fspring-data",{"title":211,"path":212,"stem":213},"Spring JDBC","\u002Fnotes\u002Fdevelopment\u002Fjava\u002Fspring-jdbc","1.notes\u002Fdevelopment\u002Fjava\u002Fspring-jdbc",{"title":215,"path":216,"stem":217},"Spring MVC","\u002Fnotes\u002Fdevelopment\u002Fjava\u002Fspring-mvc-presentation","1.notes\u002Fdevelopment\u002Fjava\u002Fspring-mvc-presentation",{"title":219,"path":220,"stem":221},"Spring Security","\u002Fnotes\u002Fdevelopment\u002Fjava\u002Fspring-security","1.notes\u002Fdevelopment\u002Fjava\u002Fspring-security",{"title":223,"path":224,"stem":225},"Testing","\u002Fnotes\u002Fdevelopment\u002Fjava\u002Ftesting","1.notes\u002Fdevelopment\u002Fjava\u002Ftesting",{"title":227,"path":228,"stem":229,"children":230,"page":30},"Js","\u002Fnotes\u002Fdevelopment\u002Fjs","1.notes\u002Fdevelopment\u002Fjs",[231,235],{"title":232,"path":233,"stem":234},"JavaScript","\u002Fnotes\u002Fdevelopment\u002Fjs\u002Fjava-script","1.notes\u002Fdevelopment\u002Fjs\u002Fjava-script",{"title":236,"path":237,"stem":238},"NodeJS","\u002Fnotes\u002Fdevelopment\u002Fjs\u002Fnode-js","1.notes\u002Fdevelopment\u002Fjs\u002Fnode-js",{"title":240,"path":241,"stem":242,"children":243,"page":30},"PowerPlatform","\u002Fnotes\u002Fdevelopment\u002Fpower_platform","1.notes\u002Fdevelopment\u002Fpower_platform",[244,248,252,256],{"title":245,"path":246,"stem":247},"Power Apps","\u002Fnotes\u002Fdevelopment\u002Fpower_platform\u002Fpower-apps","1.notes\u002Fdevelopment\u002Fpower_platform\u002Fpower-apps",{"title":249,"path":250,"stem":251},"Power Automate","\u002Fnotes\u002Fdevelopment\u002Fpower_platform\u002Fpower-automate","1.notes\u002Fdevelopment\u002Fpower_platform\u002Fpower-automate",{"title":253,"path":254,"stem":255},"Power BI","\u002Fnotes\u002Fdevelopment\u002Fpower_platform\u002Fpower-bi","1.notes\u002Fdevelopment\u002Fpower_platform\u002Fpower-bi",{"title":257,"path":258,"stem":259},"Sharepoint","\u002Fnotes\u002Fdevelopment\u002Fpower_platform\u002Fsharepoint","1.notes\u002Fdevelopment\u002Fpower_platform\u002Fsharepoint",{"title":261,"path":262,"stem":263},"Python","\u002Fnotes\u002Fdevelopment\u002Fpython","1.notes\u002Fdevelopment\u002Fpython",{"title":265,"path":266,"stem":267,"children":268,"page":30},"Devops","\u002Fnotes\u002Fdevops","1.notes\u002Fdevops",[269,273,277,281,285,289,293,297,306],{"title":270,"path":271,"stem":272},"Containers","\u002Fnotes\u002Fdevops\u002Fcontainers","1.notes\u002Fdevops\u002Fcontainers",{"title":274,"path":275,"stem":276},"Curl","\u002Fnotes\u002Fdevops\u002Fcurl","1.notes\u002Fdevops\u002Fcurl",{"title":278,"path":279,"stem":280},"GCP","\u002Fnotes\u002Fdevops\u002Fgcp","1.notes\u002Fdevops\u002Fgcp",{"title":282,"path":283,"stem":284},"GIT","\u002Fnotes\u002Fdevops\u002Fgit","1.notes\u002Fdevops\u002Fgit",{"title":286,"path":287,"stem":288},"Jenkins","\u002Fnotes\u002Fdevops\u002Fjenkins","1.notes\u002Fdevops\u002Fjenkins",{"title":290,"path":291,"stem":292},"Kubernetes","\u002Fnotes\u002Fdevops\u002Fkubernetes","1.notes\u002Fdevops\u002Fkubernetes",{"title":294,"path":295,"stem":296},"Linux","\u002Fnotes\u002Fdevops\u002Flinux","1.notes\u002Fdevops\u002Flinux",{"title":298,"path":299,"stem":300,"children":301,"page":30},"Os","\u002Fnotes\u002Fdevops\u002Fos","1.notes\u002Fdevops\u002Fos",[302],{"title":303,"path":304,"stem":305},"MAC OS","\u002Fnotes\u002Fdevops\u002Fos\u002Fmacos","1.notes\u002Fdevops\u002Fos\u002Fmacos",{"title":307,"path":308,"stem":309},"WSL","\u002Fnotes\u002Fdevops\u002Fwsl","1.notes\u002Fdevops\u002Fwsl",{"title":311,"path":312,"stem":313,"children":314,"page":30},"Hardware","\u002Fnotes\u002Fhardware","1.notes\u002Fhardware",[315],{"title":316,"path":317,"stem":318},"Keyboard","\u002Fnotes\u002Fhardware\u002Fkeyboard","1.notes\u002Fhardware\u002Fkeyboard",{"title":320,"path":321,"stem":322,"children":323,"page":30},"Homelab","\u002Fnotes\u002Fhomelab","1.notes\u002Fhomelab",[324,328,337,350],{"title":325,"path":326,"stem":327},"Proxmox","\u002Fnotes\u002Fhomelab\u002F_-proxmox-1","1.notes\u002Fhomelab\u002F_ proxmox 1",{"title":329,"path":330,"stem":331,"children":332,"page":30},"Cloudflare","\u002Fnotes\u002Fhomelab\u002Fcloudflare","1.notes\u002Fhomelab\u002Fcloudflare",[333],{"title":334,"path":335,"stem":336},"Cloudflare Workers","\u002Fnotes\u002Fhomelab\u002Fcloudflare\u002Fworkers","1.notes\u002Fhomelab\u002Fcloudflare\u002Fworkers",{"title":338,"path":339,"stem":340,"children":341,"page":30},"HomeAssistant","\u002Fnotes\u002Fhomelab\u002Fhome_assistant","1.notes\u002Fhomelab\u002Fhome_assistant",[342,346],{"title":343,"path":344,"stem":345},"EspHome debugger","\u002Fnotes\u002Fhomelab\u002Fhome_assistant\u002Fesphome-debugger","1.notes\u002Fhomelab\u002Fhome_assistant\u002Fesphome-debugger",{"title":347,"path":348,"stem":349},"GIT integration","\u002Fnotes\u002Fhomelab\u002Fhome_assistant\u002Fgit-integration","1.notes\u002Fhomelab\u002Fhome_assistant\u002Fgit-integration",{"title":325,"path":351,"stem":352,"children":353},"\u002Fnotes\u002Fhomelab\u002Fproxmox","1.notes\u002Fhomelab\u002Fproxmox",[354,358,362,365,369,373,377],{"title":355,"path":356,"stem":357},"Issue: TASK ERROR: Device \u002Fdev\u002Fdri\u002Fcard1 does not exist","\u002Fnotes\u002Fhomelab\u002Fproxmox\u002Fissue_task_error_device_dev_dri_card1_does-not-exist","1.notes\u002Fhomelab\u002Fproxmox\u002FIssue_TASK_ERROR_device_dev_dri_card1_does not exist",{"title":359,"path":360,"stem":361},"Mount USB Drive To LXC Container","\u002Fnotes\u002Fhomelab\u002Fproxmox\u002Fmount-usb-drive-to-lxc-container","1.notes\u002Fhomelab\u002Fproxmox\u002FMount USB drive to LXC container",{"title":325,"path":363,"stem":364},"\u002Fnotes\u002Fhomelab\u002Fproxmox\u002F_-proxmox","1.notes\u002Fhomelab\u002Fproxmox\u002F_ proxmox",{"title":366,"path":367,"stem":368},"ARR","\u002Fnotes\u002Fhomelab\u002Fproxmox\u002Farr","1.notes\u002Fhomelab\u002Fproxmox\u002Farr",{"title":370,"path":371,"stem":372},"Auto login via SSH from Proxmox UI","\u002Fnotes\u002Fhomelab\u002Fproxmox\u002Fauto_login_via_ssh_from_proxmox_ui","1.notes\u002Fhomelab\u002Fproxmox\u002Fauto_login_via_ssh_from_proxmox_ui",{"title":374,"path":375,"stem":376},"Installation","\u002Fnotes\u002Fhomelab\u002Fproxmox\u002Fdokploy","1.notes\u002Fhomelab\u002Fproxmox\u002Fdokploy",{"title":290,"path":378,"stem":379},"\u002Fnotes\u002Fhomelab\u002Fproxmox\u002Fkubernetes","1.notes\u002Fhomelab\u002Fproxmox\u002Fkubernetes",{"title":381,"path":382,"stem":383,"children":384,"page":30},"Leadership","\u002Fnotes\u002Fleadership","1.notes\u002Fleadership",[385,389,393],{"title":386,"path":387,"stem":388},"Leader Toolbox","\u002Fnotes\u002Fleadership\u002Fleader-toolbox","1.notes\u002Fleadership\u002Fleader-toolbox",{"title":390,"path":391,"stem":392},"Enterprise Project Structure","\u002Fnotes\u002Fleadership\u002Fproject-doc-structure","1.notes\u002Fleadership\u002Fproject-doc-structure",{"title":394,"path":395,"stem":396},"Scrum template","\u002Fnotes\u002Fleadership\u002Fscrum-template","1.notes\u002Fleadership\u002Fscrum-template",{"title":398,"path":399,"stem":400,"children":401,"page":30},"Products","\u002Fnotes\u002Fproducts","1.notes\u002Fproducts",[402],{"title":403,"path":404,"stem":405},"BigQuery","\u002Fnotes\u002Fproducts\u002Fgcp-big-query","1.notes\u002Fproducts\u002Fgcp-big-query",{"id":407,"title":408,"body":409,"description":410,"extension":411,"meta":412,"navigation":413,"path":415,"seo":416,"stem":417,"__hash__":418},"blog\u002F2.blog.yml","Blog",null,"Discover the latest insights, tutorials, and updates from our team. Stay informed about web development trends, best practices, and innovative solutions.","yml",{},{"icon":414},"i-lucide-newspaper","\u002Fblog",{"title":408,"description":410},"2.blog","rT8mkXq4CwMBcTEK_4-sSfWkdHtl8tDGcVIMrnPpEUc",[420,998,2134,2528,2733,3049,3455,3765,4022,4156,5580,5665,6001,6302,6645,7496,7920,7998,10770,12794,12895,12933,13260],{"id":421,"title":45,"authors":409,"badge":409,"body":422,"date":989,"description":990,"extension":991,"image":409,"meta":992,"navigation":474,"path":994,"seo":995,"stem":996,"__hash__":997},"posts\u002F2.blog\u002F2010-12-14-gwt-basic-components.md",{"type":423,"value":424,"toc":987},"minimark",[425,429,432,435,438,448,451,568,571,579,582,590,596,812,815,895,898,908,967,970,973,983],[426,427,428],"p",{},"aaa\nGoogle Web Toolkit (GWT) jest szkieletem do tworzenia aplikacji AJAX w oparciu o język Java. Pozwala on na tworzenie kodu bez ręcznego kodowania i łączenia elementów języka Java oraz JavaScript. Po napisaniu kodu aplikacji następuje kompilacja części klienckiej do JavaScriptu, CSS oraz HTML. Część serwerowa zostaje skompilowana przez standardowy kompilator Javy. Framework w standardzie zapewnia poprawne wyświetlanie komponentów w przeglądarkach: Firefox, Opera, IE, Safari, Google Chrome. (Wikipedia.pl)",[426,430,431],{},"W skrócie GWT jest frameworkiem, który pozwala na tworzenie aplikacji typu RIA w całości w języku Java. Projekt GWT składa się z części klienckiej i serwerowej. Część kliencka umieszczona jest w odpowiedniej paczce (zazwyczaj client) i podczas kompilacji jest konwertowana za pomocą kompilatora skrośnego do postaci Java Scriptu – formy obsługiwanej natywnie przez przeglądarki internetowe.\nPodczas ładowania strony to właśnie część kliencka ładowana jest w całości do pamięci przeglądarki. Dzięki temu każde przejście pomiędzy kolejnymi stronami czy interakcja z komponentami – widgetami nie musi oznaczać przeładowania całej strony. Dzięki temu, że wygenerowany i zoptymalizowany! kod Java Script operuje na elementach DOM naszej strony odnosimy wrażenie, że mamy do czynienia niemal z tradycyjną aplikacją desktopową.\nAplikacja nie musi koniecznie znajdować się na serwerze aplikacji Java. Skompilowana część kliencka może zostać umieszczona na dowolnym serwerze. Dzięki możliwości parsowania plików XML czy JSON GWT może komunikować się z dowolnym WebService-m. Natywnie jednak GWT wspiera komunikację poprzez GWT-RPC – mechanizm asynchronicznej komunikacji z częścią serwerową napisaną w języku Java.",[426,433,434],{},"To są jedynie podstawowe zalety GWT, których w rzeczywistości jest cała masa. Według nas jest to obecnie jeden z najlepszych frameworków pozwalających na tworzenie aplikacji typu RIA a w tym artykule opiszemy jedynie podstawowe komponenty typowego projektu GWT. Osoby, które chciałyby rozpocząć pracę z GWT zapraszamy na stronę projektu, gdzie znajduje się szczegółowy poradnik jak uruchomić pierwszy projekt. Po nieco przydługawym wstępie przystępujemy do omawiania najważniejszych elementów.",[426,436,437],{},"Każda aplikacja GWT ma budowę modułową, dlatego też każda aplikacja musi posiadać moduł główny. Każdy moduł musi składać się przynajmniej z 2 elementów:",[439,440,441,445],"ul",{},[442,443,444],"li",{},"Deskryptora modułów",[442,446,447],{},"Punktu wejścia",[426,449,450],{},"Deskryptor modułów jest to plik xml znajdujący się w paczce w której znajdować się będą zasoby modułu. Nazwa deskryptora będzie określać nazwę całego modułu, np.: Main.gwt.xml sprawi, że moduł ten będzie nazwyać się Main i zawiera on informacje na temat wykorzystywanych zewnętrznych modułów (np. widgetów)",[452,453,458],"pre",{"className":454,"code":455,"language":456,"meta":457,"style":457},"language-xml shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u003C?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n\u003C!DOCTYPE module PUBLIC \"-\u002F\u002FGoogle Inc.\u002F\u002FDTD Google Web Toolkit 1.7.0\u002F\u002FEN\" \"http:\u002F\u002Fgoogle-web-toolkit.googlecode.com\u002Fsvn\u002Ftags\u002F1.7.0\u002Fdistro-source\u002Fcore\u002Fsrc\u002Fgwt-module.dtd\">\n\n\u003Cmodule>\n    \u003Cinherits name=\"com.google.gwt.user.User\"\u002F>\n\n    \u003C!-- Inherit the default GWT style sheet. You can change -->\n    \u003C!-- the theme of your GWT application by uncommenting -->\n    \u003C!-- any one of the following lines. -->\n    \u003C!-- \u003Cinherits name='com.google.gwt.user.theme.standard.Standard'\u002F> -->\n    \u003C!-- \u003Cinherits name=\"com.google.gwt.user.theme.chrome.Chrome\"\u002F> -->\n    \u003C!-- \u003Cinherits name=\"com.google.gwt.user.theme.dark.Dark\"\u002F> -->\n\n    \u003Centry-point class=\"pl.testing.client.MainEntryPoint\"\u002F>\n\n    \u003C!-- Do not define servlets here, use web.xml -->\n\u003C\u002Fmodule>\n","xml","",[459,460,461,469,476,482,487,493,499,504,510,516,522,528,534,540,545,551,556,562],"code",{"__ignoreMap":457},[462,463,466],"span",{"class":464,"line":465},"line",1,[462,467,468],{},"\u003C?xml version=\"1.0\" encoding=\"UTF-8\"?>\n",[462,470,472],{"class":464,"line":471},2,[462,473,475],{"emptyLinePlaceholder":474},true,"\n",[462,477,479],{"class":464,"line":478},3,[462,480,481],{},"\u003C!DOCTYPE module PUBLIC \"-\u002F\u002FGoogle Inc.\u002F\u002FDTD Google Web Toolkit 1.7.0\u002F\u002FEN\" \"http:\u002F\u002Fgoogle-web-toolkit.googlecode.com\u002Fsvn\u002Ftags\u002F1.7.0\u002Fdistro-source\u002Fcore\u002Fsrc\u002Fgwt-module.dtd\">\n",[462,483,485],{"class":464,"line":484},4,[462,486,475],{"emptyLinePlaceholder":474},[462,488,490],{"class":464,"line":489},5,[462,491,492],{},"\u003Cmodule>\n",[462,494,496],{"class":464,"line":495},6,[462,497,498],{},"    \u003Cinherits name=\"com.google.gwt.user.User\"\u002F>\n",[462,500,502],{"class":464,"line":501},7,[462,503,475],{"emptyLinePlaceholder":474},[462,505,507],{"class":464,"line":506},8,[462,508,509],{},"    \u003C!-- Inherit the default GWT style sheet. You can change -->\n",[462,511,513],{"class":464,"line":512},9,[462,514,515],{},"    \u003C!-- the theme of your GWT application by uncommenting -->\n",[462,517,519],{"class":464,"line":518},10,[462,520,521],{},"    \u003C!-- any one of the following lines. -->\n",[462,523,525],{"class":464,"line":524},11,[462,526,527],{},"    \u003C!-- \u003Cinherits name='com.google.gwt.user.theme.standard.Standard'\u002F> -->\n",[462,529,531],{"class":464,"line":530},12,[462,532,533],{},"    \u003C!-- \u003Cinherits name=\"com.google.gwt.user.theme.chrome.Chrome\"\u002F> -->\n",[462,535,537],{"class":464,"line":536},13,[462,538,539],{},"    \u003C!-- \u003Cinherits name=\"com.google.gwt.user.theme.dark.Dark\"\u002F> -->\n",[462,541,543],{"class":464,"line":542},14,[462,544,475],{"emptyLinePlaceholder":474},[462,546,548],{"class":464,"line":547},15,[462,549,550],{},"    \u003Centry-point class=\"pl.testing.client.MainEntryPoint\"\u002F>\n",[462,552,554],{"class":464,"line":553},16,[462,555,475],{"emptyLinePlaceholder":474},[462,557,559],{"class":464,"line":558},17,[462,560,561],{},"    \u003C!-- Do not define servlets here, use web.xml -->\n",[462,563,565],{"class":464,"line":564},18,[462,566,567],{},"\u003C\u002Fmodule>\n",[426,569,570],{},"Aby móc wykorzystywać biblioteki zewnętrzne w części klienckiej naszej aplikacji (np dodatkowe widgety) musimy dodać taką bibliotekę do naszego classpatha oraz dodać wpis inherits w deskryptorze modułów np:",[452,572,573],{"className":454,"code":498,"language":456,"meta":457,"style":457},[459,574,575],{"__ignoreMap":457},[462,576,577],{"class":464,"line":465},[462,578,498],{},[426,580,581],{},"Dlaczego nie wystarczy dodać naszej biblioteki do classpatha i po prostu zacząć z nich korzystać? Niestety jest to trochę skomplikowane. Nie dość, że musimy obowiązkowo dodawać dodatkowe wpisy w deskryptorze to jeszcze nie mogą to być dowolne biblioteki. Muszą to być koniecznie skompilowane w specjalny sposób moduły GWT, które kompilator skrośny jest w stanie przetworzyć do Java Scriptu. Niestety pisząc część kliencką jesteśmy ograniczeni do tzw. środowiska emulowanego. Niestety nie wszystko da się skompilować do postaci Java Scriptu, dlatego użytkownicy są ograniczeni do korzystania z jedynie wybranych klas przygotowanych specjalnie przez Google. Gdy korzystamy z klasy Date, albo String w rzeczywistości wykorzystujemy nadpisaną przez Google klasę, która posiada identyczne metody i zachowanie co oryginalna klasa. Różnią się one jednak tym, że te przesłaniające można skompilować do JS. Obecnie wachlarz udostępnionych klas jest naprawdę ogromny i mówi się, że zaemulowane jest niemalże w pełni środowisko znane z Javy 1.4 z wieloma dodatkami nowszych wersji np. Genericki. Niestety największą bolączką i czymś, co będzie bardzo trudne w przeskoczeniu jest refleksja. Niestety JS nie wspiera refleksji przez co dodawanie kolejnych funkcjonalności, które mogą być zawarte w emulowanym środowisku jest niezwykle utrudnione.\nPodsumowując aktualny akapit: aby móc wykorzystywać wspierane zewnętrzne biblioteki przez moduł GWT należy dodać ją do Classpatha oraz do deskryptora bieżącego modułu.\nKolejnym ważnym elementem w deskryptorze jest:",[452,583,584],{"className":454,"code":550,"language":456,"meta":457,"style":457},[459,585,586],{"__ignoreMap":457},[462,587,588],{"class":464,"line":465},[462,589,550],{},[426,591,592,593,595],{},"Jest to tzw. punkt wejścia modułu. Jest to nic innego jak tylko odpowiednik klasy zawierającej metodę public void main(String",[462,594],{}," args). Dzięki temu wpisowi podczas uruchamiania wskazanego modułu ładowana jest właśnie klasa pl.testing.client.MainEntryPoint, która musi implementować interfejs EntryPoint i znajdować się w części klienckiej naszego modułu (podfolder client):",[452,597,601],{"className":598,"code":599,"language":600,"meta":457,"style":457},"language-java shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","package pl.testing.client;\n\nimport com.google.gwt.core.client.EntryPoint;\nimport com.google.gwt.user.client.ui.Button;\nimport com.google.gwt.user.client.ui.Label;\nimport com.google.gwt.user.client.ui.RootPanel;\nimport com.google.gwt.event.dom.client.ClickEvent;\nimport com.google.gwt.event.dom.client.ClickHandler;\n\n\u002F**\n * Main entry point.\n *\n * @author Praca\n *\u002F\npublic class MainEntryPoint implements EntryPoint {\n    \u002F** \n     * Creates a new instance of MainEntryPoint\n     *\u002F\n    public MainEntryPoint() {\n    }\n\n    \u002F** \n     * The entry point method, called automatically by loading a module\n     * that declares an implementing class as an entry-point\n     *\u002F\n    public void onModuleLoad() {\n        final Label label = new Label(\"Hello, GWT!!!\");\n        final Button button = new Button(\"Click me!\");\n        \n        button.addClickHandler(new ClickHandler() {\n            public void onClick(ClickEvent event) {\n                label.setVisible(!label.isVisible());\n            }\n        });\n\n        RootPanel.get().add(button);\n        RootPanel.get().add(label);\n    }\n}\n","java",[459,602,603,608,612,617,622,627,632,637,642,646,651,656,661,666,671,676,681,686,691,697,703,708,713,719,725,730,736,742,748,754,760,766,772,778,784,789,795,801,806],{"__ignoreMap":457},[462,604,605],{"class":464,"line":465},[462,606,607],{},"package pl.testing.client;\n",[462,609,610],{"class":464,"line":471},[462,611,475],{"emptyLinePlaceholder":474},[462,613,614],{"class":464,"line":478},[462,615,616],{},"import com.google.gwt.core.client.EntryPoint;\n",[462,618,619],{"class":464,"line":484},[462,620,621],{},"import com.google.gwt.user.client.ui.Button;\n",[462,623,624],{"class":464,"line":489},[462,625,626],{},"import com.google.gwt.user.client.ui.Label;\n",[462,628,629],{"class":464,"line":495},[462,630,631],{},"import com.google.gwt.user.client.ui.RootPanel;\n",[462,633,634],{"class":464,"line":501},[462,635,636],{},"import com.google.gwt.event.dom.client.ClickEvent;\n",[462,638,639],{"class":464,"line":506},[462,640,641],{},"import com.google.gwt.event.dom.client.ClickHandler;\n",[462,643,644],{"class":464,"line":512},[462,645,475],{"emptyLinePlaceholder":474},[462,647,648],{"class":464,"line":518},[462,649,650],{},"\u002F**\n",[462,652,653],{"class":464,"line":524},[462,654,655],{}," * Main entry point.\n",[462,657,658],{"class":464,"line":530},[462,659,660],{}," *\n",[462,662,663],{"class":464,"line":536},[462,664,665],{}," * @author Praca\n",[462,667,668],{"class":464,"line":542},[462,669,670],{}," *\u002F\n",[462,672,673],{"class":464,"line":547},[462,674,675],{},"public class MainEntryPoint implements EntryPoint {\n",[462,677,678],{"class":464,"line":553},[462,679,680],{},"    \u002F** \n",[462,682,683],{"class":464,"line":558},[462,684,685],{},"     * Creates a new instance of MainEntryPoint\n",[462,687,688],{"class":464,"line":564},[462,689,690],{},"     *\u002F\n",[462,692,694],{"class":464,"line":693},19,[462,695,696],{},"    public MainEntryPoint() {\n",[462,698,700],{"class":464,"line":699},20,[462,701,702],{},"    }\n",[462,704,706],{"class":464,"line":705},21,[462,707,475],{"emptyLinePlaceholder":474},[462,709,711],{"class":464,"line":710},22,[462,712,680],{},[462,714,716],{"class":464,"line":715},23,[462,717,718],{},"     * The entry point method, called automatically by loading a module\n",[462,720,722],{"class":464,"line":721},24,[462,723,724],{},"     * that declares an implementing class as an entry-point\n",[462,726,728],{"class":464,"line":727},25,[462,729,690],{},[462,731,733],{"class":464,"line":732},26,[462,734,735],{},"    public void onModuleLoad() {\n",[462,737,739],{"class":464,"line":738},27,[462,740,741],{},"        final Label label = new Label(\"Hello, GWT!!!\");\n",[462,743,745],{"class":464,"line":744},28,[462,746,747],{},"        final Button button = new Button(\"Click me!\");\n",[462,749,751],{"class":464,"line":750},29,[462,752,753],{},"        \n",[462,755,757],{"class":464,"line":756},30,[462,758,759],{},"        button.addClickHandler(new ClickHandler() {\n",[462,761,763],{"class":464,"line":762},31,[462,764,765],{},"            public void onClick(ClickEvent event) {\n",[462,767,769],{"class":464,"line":768},32,[462,770,771],{},"                label.setVisible(!label.isVisible());\n",[462,773,775],{"class":464,"line":774},33,[462,776,777],{},"            }\n",[462,779,781],{"class":464,"line":780},34,[462,782,783],{},"        });\n",[462,785,787],{"class":464,"line":786},35,[462,788,475],{"emptyLinePlaceholder":474},[462,790,792],{"class":464,"line":791},36,[462,793,794],{},"        RootPanel.get().add(button);\n",[462,796,798],{"class":464,"line":797},37,[462,799,800],{},"        RootPanel.get().add(label);\n",[462,802,804],{"class":464,"line":803},38,[462,805,702],{},[462,807,809],{"class":464,"line":808},39,[462,810,811],{},"}\n",[426,813,814],{},"Kolejnym podstawowym elementem jest strona ładująca. Jest to strona, która zostanie wczytana przez przeglądarkę i załaduje całą naszą aplikację do pamięci przeglądarki.",[452,816,818],{"className":454,"code":817,"language":456,"meta":457,"style":457},"\u003C!doctype html>\n\u003C!--\nThe DOCTYPE declaration above will set the browser's rendering engine into\n\"Standards Mode\". Replacing this declaration with a \"Quirks Mode\" doctype may\nlead to some differences in layout.\n-->\n\u003Chtml>\n    \u003Chead>\n        \u003Cmeta name='gwt:module' content='pl.testing.Main=pl.testing.Main'>\n        \u003Ctitle>Main\u003C\u002Ftitle>\n    \u003C\u002Fhead>\n    \u003Cbody>\n        \u003Cscript type=\"text\u002Fjavascript\"  src=\"pl.testing.Main\u002Fpl.testing.Main.nocache.js\">\u003C\u002Fscript>\n    \u003C\u002Fbody>\n\u003C\u002Fhtml>\n",[459,819,820,825,830,835,840,845,850,855,860,865,870,875,880,885,890],{"__ignoreMap":457},[462,821,822],{"class":464,"line":465},[462,823,824],{},"\u003C!doctype html>\n",[462,826,827],{"class":464,"line":471},[462,828,829],{},"\u003C!--\n",[462,831,832],{"class":464,"line":478},[462,833,834],{},"The DOCTYPE declaration above will set the browser's rendering engine into\n",[462,836,837],{"class":464,"line":484},[462,838,839],{},"\"Standards Mode\". Replacing this declaration with a \"Quirks Mode\" doctype may\n",[462,841,842],{"class":464,"line":489},[462,843,844],{},"lead to some differences in layout.\n",[462,846,847],{"class":464,"line":495},[462,848,849],{},"-->\n",[462,851,852],{"class":464,"line":501},[462,853,854],{},"\u003Chtml>\n",[462,856,857],{"class":464,"line":506},[462,858,859],{},"    \u003Chead>\n",[462,861,862],{"class":464,"line":512},[462,863,864],{},"        \u003Cmeta name='gwt:module' content='pl.testing.Main=pl.testing.Main'>\n",[462,866,867],{"class":464,"line":518},[462,868,869],{},"        \u003Ctitle>Main\u003C\u002Ftitle>\n",[462,871,872],{"class":464,"line":524},[462,873,874],{},"    \u003C\u002Fhead>\n",[462,876,877],{"class":464,"line":530},[462,878,879],{},"    \u003Cbody>\n",[462,881,882],{"class":464,"line":536},[462,883,884],{},"        \u003Cscript type=\"text\u002Fjavascript\"  src=\"pl.testing.Main\u002Fpl.testing.Main.nocache.js\">\u003C\u002Fscript>\n",[462,886,887],{"class":464,"line":542},[462,888,889],{},"    \u003C\u002Fbody>\n",[462,891,892],{"class":464,"line":547},[462,893,894],{},"\u003C\u002Fhtml>\n",[426,896,897],{},"Najważniejszymi tutaj są:",[426,899,900,903,904,907],{},[459,901,902],{},"\u003Cmeta name=’gwt:module’ content=’pl.testing.Main=pl.testing.Main’>"," – określa główny moduł\n",[459,905,906],{},"\u003Cscript type=”text\u002Fjavascript” src=”pl.testing.Main\u002Fpl.testing.Main.nocache.js”&gt\u003C\u002Fscript>"," – skrypt ładujący skompilowaną aplikację do javy scriptu\nPlik konfiguracyjny aplikacji, zawierający na początku jedynie wpis o stronie ładującej aplikację JEE powinien wyglądać mniej więcej tak:",[452,909,911],{"className":454,"code":910,"language":456,"meta":457,"style":457},"\u003C?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\u003Cweb-app version=\"2.5\" xmlns=\"http:\u002F\u002Fjava.sun.com\u002Fxml\u002Fns\u002Fjavaee\" xmlns:xsi=\"http:\u002F\u002Fwww.w3.org\u002F2001\u002FXMLSchema-instance\" xsi:schemaLocation=\"http:\u002F\u002Fjava.sun.com\u002Fxml\u002Fns\u002Fjavaee http:\u002F\u002Fjava.sun.com\u002Fxml\u002Fns\u002Fjavaee\u002Fweb-app_2_5.xsd\">\n    \u003Csession-config>\n        \u003Csession-timeout>\n            30\n        \u003C\u002Fsession-timeout>\n    \u003C\u002Fsession-config>\n    \u003Cwelcome-file-list>\n        \u003Cwelcome-file>welcomeGWT.html\u003C\u002Fwelcome-file>\n    \u003C\u002Fwelcome-file-list>\n\u003C\u002Fweb-app>\n",[459,912,913,917,922,927,932,937,942,947,952,957,962],{"__ignoreMap":457},[462,914,915],{"class":464,"line":465},[462,916,468],{},[462,918,919],{"class":464,"line":471},[462,920,921],{},"\u003Cweb-app version=\"2.5\" xmlns=\"http:\u002F\u002Fjava.sun.com\u002Fxml\u002Fns\u002Fjavaee\" xmlns:xsi=\"http:\u002F\u002Fwww.w3.org\u002F2001\u002FXMLSchema-instance\" xsi:schemaLocation=\"http:\u002F\u002Fjava.sun.com\u002Fxml\u002Fns\u002Fjavaee http:\u002F\u002Fjava.sun.com\u002Fxml\u002Fns\u002Fjavaee\u002Fweb-app_2_5.xsd\">\n",[462,923,924],{"class":464,"line":478},[462,925,926],{},"    \u003Csession-config>\n",[462,928,929],{"class":464,"line":484},[462,930,931],{},"        \u003Csession-timeout>\n",[462,933,934],{"class":464,"line":489},[462,935,936],{},"            30\n",[462,938,939],{"class":464,"line":495},[462,940,941],{},"        \u003C\u002Fsession-timeout>\n",[462,943,944],{"class":464,"line":501},[462,945,946],{},"    \u003C\u002Fsession-config>\n",[462,948,949],{"class":464,"line":506},[462,950,951],{},"    \u003Cwelcome-file-list>\n",[462,953,954],{"class":464,"line":512},[462,955,956],{},"        \u003Cwelcome-file>welcomeGWT.html\u003C\u002Fwelcome-file>\n",[462,958,959],{"class":464,"line":518},[462,960,961],{},"    \u003C\u002Fwelcome-file-list>\n",[462,963,964],{"class":464,"line":524},[462,965,966],{},"\u003C\u002Fweb-app>\n",[426,968,969],{},"W przyszłych wpisach przyjżymy się jemu bliżej a większość konfiguracji związanych z mapowaniem servletów, które muszą znajdować się właśnie w tym pliku przeniesiemy do wygodnego modułu.",[426,971,972],{},"Ostatnim elementem, który należy wspomnieć to kompilacja projektu. Aplikację taką można kompilować zarówno za pomocą Anta jak i Mavena. Nie będziemy zagłębiać się tutaj w szczegóły na ten temat, ponieważ większość czynności wykonują za nas IDE wraz z odpowiednimi wtyczkami.",[426,974,975,976,982],{},"Spragnionych większej dawki wiedzy odsyłam do strony domowej frameworka: ",[977,978,979],"a",{"href":979,"rel":980},"http:\u002F\u002Fcode.google.com\u002Fintl\u002Fpl-PL\u002Fwebtoolkit\u002F",[981],"nofollow"," .\nW następnej części już szczegółowo zajmiemy się Guice-m oraz Hibernate-m.",[984,985,986],"style",{},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":457,"searchDepth":471,"depth":471,"links":988},[],"2010-12-14","Opis i podstawowe elementy (in Polish)","md",{"layout":993},"post","\u002Fblog\u002F2010-12-14-gwt-basic-components",{"title":45,"description":990},"2.blog\u002F2010-12-14-gwt-basic-components","ti8wFjTopBfRMSu5kR-nI0qd4KQ1fXtpK_VAOq3lrXI",{"id":999,"title":1000,"authors":409,"badge":409,"body":1001,"date":2127,"description":2128,"extension":991,"image":409,"meta":2129,"navigation":474,"path":2130,"seo":2131,"stem":2132,"__hash__":2133},"posts\u002F2.blog\u002F2010-12-15-gwt-and-guice.md","Google Web Toolkit + Guice",{"type":423,"value":1002,"toc":2125},[1003,1006,1086,1089,1126,1129,1148,1151,1203,1206,1301,1304,1313,1316,1336,1339,1375,1378,1426,1429,1432,1477,1480,1524,1527,1530,1572,1575,1608,1614,1617,1705,1708,1711,1754,1757,1766,1769,1778,1781,1790,1793,1796,1833,1836,1839,1942,2120,2123],[426,1004,1005],{},"Guice jest frameworkiem dostarczającym tzn. wstrzykiwania zależności w naszej części serwerowej aplikacji.\nGdybyśmy rozważali aplikację typu desktop poniższa konfiguracja w zupełności by wystarczyła:",[452,1007,1009],{"className":598,"code":1008,"language":600,"meta":457,"style":457},"package testingguice;\n\nimport com.google.inject.AbstractModule;\nimport com.google.inject.Guice;\nimport com.google.inject.Injector;\n\npublic class Main {\n\n    public static void main(String[] args) {\n        Injector injector = Guice.createInjector(new MyModule());\n        PersonDao personDao = injector.getInstance(PersonDao.class);\n        for (Person person : personDao.getAll()) {\n            System.out.println(\"Person: \"+person);\n        }\n    }\n}\n",[459,1010,1011,1016,1020,1025,1030,1035,1039,1044,1048,1053,1058,1063,1068,1073,1078,1082],{"__ignoreMap":457},[462,1012,1013],{"class":464,"line":465},[462,1014,1015],{},"package testingguice;\n",[462,1017,1018],{"class":464,"line":471},[462,1019,475],{"emptyLinePlaceholder":474},[462,1021,1022],{"class":464,"line":478},[462,1023,1024],{},"import com.google.inject.AbstractModule;\n",[462,1026,1027],{"class":464,"line":484},[462,1028,1029],{},"import com.google.inject.Guice;\n",[462,1031,1032],{"class":464,"line":489},[462,1033,1034],{},"import com.google.inject.Injector;\n",[462,1036,1037],{"class":464,"line":495},[462,1038,475],{"emptyLinePlaceholder":474},[462,1040,1041],{"class":464,"line":501},[462,1042,1043],{},"public class Main {\n",[462,1045,1046],{"class":464,"line":506},[462,1047,475],{"emptyLinePlaceholder":474},[462,1049,1050],{"class":464,"line":512},[462,1051,1052],{},"    public static void main(String[] args) {\n",[462,1054,1055],{"class":464,"line":518},[462,1056,1057],{},"        Injector injector = Guice.createInjector(new MyModule());\n",[462,1059,1060],{"class":464,"line":524},[462,1061,1062],{},"        PersonDao personDao = injector.getInstance(PersonDao.class);\n",[462,1064,1065],{"class":464,"line":530},[462,1066,1067],{},"        for (Person person : personDao.getAll()) {\n",[462,1069,1070],{"class":464,"line":536},[462,1071,1072],{},"            System.out.println(\"Person: \"+person);\n",[462,1074,1075],{"class":464,"line":542},[462,1076,1077],{},"        }\n",[462,1079,1080],{"class":464,"line":547},[462,1081,702],{},[462,1083,1084],{"class":464,"line":553},[462,1085,811],{},[426,1087,1088],{},"Klasa modułu w rozumieniu IoC:",[452,1090,1092],{"className":598,"code":1091,"language":600,"meta":457,"style":457},"public class MyModule extends AbstractModule {\n\n    @Override\n    protected void configure() {\n        bind(PersonDao.class).to(PersonDaoImpl.class);\n    }\n}\n",[459,1093,1094,1099,1103,1108,1113,1118,1122],{"__ignoreMap":457},[462,1095,1096],{"class":464,"line":465},[462,1097,1098],{},"public class MyModule extends AbstractModule {\n",[462,1100,1101],{"class":464,"line":471},[462,1102,475],{"emptyLinePlaceholder":474},[462,1104,1105],{"class":464,"line":478},[462,1106,1107],{},"    @Override\n",[462,1109,1110],{"class":464,"line":484},[462,1111,1112],{},"    protected void configure() {\n",[462,1114,1115],{"class":464,"line":489},[462,1116,1117],{},"        bind(PersonDao.class).to(PersonDaoImpl.class);\n",[462,1119,1120],{"class":464,"line":495},[462,1121,702],{},[462,1123,1124],{"class":464,"line":501},[462,1125,811],{},[426,1127,1128],{},"Interfejs przykładowego DAO dla klasy Person:",[452,1130,1132],{"className":598,"code":1131,"language":600,"meta":457,"style":457},"public interface PersonDao {\n    public List\u003CPerson> getAll();\n}\n",[459,1133,1134,1139,1144],{"__ignoreMap":457},[462,1135,1136],{"class":464,"line":465},[462,1137,1138],{},"public interface PersonDao {\n",[462,1140,1141],{"class":464,"line":471},[462,1142,1143],{},"    public List\u003CPerson> getAll();\n",[462,1145,1146],{"class":464,"line":478},[462,1147,811],{},[426,1149,1150],{},"Implementacja naszego interfejsu, którą dzięki IoC możemy w łatwy sposób podmienić na inną implementującą ten sam interfejs:",[452,1152,1154],{"className":598,"code":1153,"language":600,"meta":457,"style":457},"public class PersonDaoImpl implements PersonDao{\n\n    public List\u003CPerson> getAll() {\n        ArrayList\u003CPerson> list = new ArrayList\u003CPerson>();\n        list.add(new Person(1, \"Jacek\"));\n        list.add(new Person(2, \"Zbyszek\"));\n        list.add(new Person(3, \"Piotrek\"));\n        return list;\n    }\n}\n",[459,1155,1156,1161,1165,1170,1175,1180,1185,1190,1195,1199],{"__ignoreMap":457},[462,1157,1158],{"class":464,"line":465},[462,1159,1160],{},"public class PersonDaoImpl implements PersonDao{\n",[462,1162,1163],{"class":464,"line":471},[462,1164,475],{"emptyLinePlaceholder":474},[462,1166,1167],{"class":464,"line":478},[462,1168,1169],{},"    public List\u003CPerson> getAll() {\n",[462,1171,1172],{"class":464,"line":484},[462,1173,1174],{},"        ArrayList\u003CPerson> list = new ArrayList\u003CPerson>();\n",[462,1176,1177],{"class":464,"line":489},[462,1178,1179],{},"        list.add(new Person(1, \"Jacek\"));\n",[462,1181,1182],{"class":464,"line":495},[462,1183,1184],{},"        list.add(new Person(2, \"Zbyszek\"));\n",[462,1186,1187],{"class":464,"line":501},[462,1188,1189],{},"        list.add(new Person(3, \"Piotrek\"));\n",[462,1191,1192],{"class":464,"line":506},[462,1193,1194],{},"        return list;\n",[462,1196,1197],{"class":464,"line":512},[462,1198,702],{},[462,1200,1201],{"class":464,"line":518},[462,1202,811],{},[426,1204,1205],{},"Przykładowe POJO wykorzystywane w DAO:",[452,1207,1209],{"className":598,"code":1208,"language":600,"meta":457,"style":457},"public class Person {\n    private int id;\n    private String name;\n\n    public Person() {\n    }\n\n    public Person(int id, String name) {\n        this.id = id;\n        this.name = name;\n    }\n\n    ...\n\n    @Override\n    public String toString() {\n        return \"Person{\" + \"id=\" + id + \",name=\" + name + '}';\n    }\n\n}\n",[459,1210,1211,1216,1221,1226,1230,1235,1239,1243,1248,1253,1258,1262,1266,1271,1275,1279,1284,1289,1293,1297],{"__ignoreMap":457},[462,1212,1213],{"class":464,"line":465},[462,1214,1215],{},"public class Person {\n",[462,1217,1218],{"class":464,"line":471},[462,1219,1220],{},"    private int id;\n",[462,1222,1223],{"class":464,"line":478},[462,1224,1225],{},"    private String name;\n",[462,1227,1228],{"class":464,"line":484},[462,1229,475],{"emptyLinePlaceholder":474},[462,1231,1232],{"class":464,"line":489},[462,1233,1234],{},"    public Person() {\n",[462,1236,1237],{"class":464,"line":495},[462,1238,702],{},[462,1240,1241],{"class":464,"line":501},[462,1242,475],{"emptyLinePlaceholder":474},[462,1244,1245],{"class":464,"line":506},[462,1246,1247],{},"    public Person(int id, String name) {\n",[462,1249,1250],{"class":464,"line":512},[462,1251,1252],{},"        this.id = id;\n",[462,1254,1255],{"class":464,"line":518},[462,1256,1257],{},"        this.name = name;\n",[462,1259,1260],{"class":464,"line":524},[462,1261,702],{},[462,1263,1264],{"class":464,"line":530},[462,1265,475],{"emptyLinePlaceholder":474},[462,1267,1268],{"class":464,"line":536},[462,1269,1270],{},"    ...\n",[462,1272,1273],{"class":464,"line":542},[462,1274,475],{"emptyLinePlaceholder":474},[462,1276,1277],{"class":464,"line":547},[462,1278,1107],{},[462,1280,1281],{"class":464,"line":553},[462,1282,1283],{},"    public String toString() {\n",[462,1285,1286],{"class":464,"line":558},[462,1287,1288],{},"        return \"Person{\" + \"id=\" + id + \",name=\" + name + '}';\n",[462,1290,1291],{"class":464,"line":564},[462,1292,702],{},[462,1294,1295],{"class":464,"line":693},[462,1296,475],{"emptyLinePlaceholder":474},[462,1298,1299],{"class":464,"line":699},[462,1300,811],{},[426,1302,1303],{},"My jednak korzystamy z aplikacji JEE, z którą nie jest aż tak łatwo. Aplikacja, która jest deployowana na serwer przed pierwszym wywołaniem strony ładującej powinna zostać zainicjonowana, co zostało zrobione w przypadku aplikacji desktopowej tu:",[452,1305,1307],{"className":598,"code":1306,"language":600,"meta":457,"style":457},"Injector injector = Guice.createInjector(new MyModule());\n",[459,1308,1309],{"__ignoreMap":457},[462,1310,1311],{"class":464,"line":465},[462,1312,1306],{},[426,1314,1315],{},"W aplikacji typu web za pomocą małego wpisu w web.xml:",[452,1317,1319],{"className":454,"code":1318,"language":456,"meta":457,"style":457},"\u003Clistener>\n  \u003Clistener-class>pl.testing.server.GuiceServletConfig\u003C\u002Flistener-class>\n\u003C\u002Flistener>\n",[459,1320,1321,1326,1331],{"__ignoreMap":457},[462,1322,1323],{"class":464,"line":465},[462,1324,1325],{},"\u003Clistener>\n",[462,1327,1328],{"class":464,"line":471},[462,1329,1330],{},"  \u003Clistener-class>pl.testing.server.GuiceServletConfig\u003C\u002Flistener-class>\n",[462,1332,1333],{"class":464,"line":478},[462,1334,1335],{},"\u003C\u002Flistener>\n",[426,1337,1338],{},"sprawiamy, że zaraz po zdeployowaniu aplikacji zostanie od razu wywołana wskazana klasa dziedzicząca po ContextListener. Wykorzystamy ten fakt do zainicjonowania naszego injectora. W tym przypadku będziemy posiłkować się dodatkowo klasą GuiceServletContextListener, która wspomaga nas i odciąża tak, że wszystko co musimy zrobić to zwrócić injector:",[452,1340,1342],{"className":598,"code":1341,"language":600,"meta":457,"style":457},"public class MainGuiceServletContextListener extends GuiceServletContextListener {\n\n    @Override\n    protected Injector getInjector() {\n        return Guice.createInjector(new MainGuiceModule());\n    }\n}\n",[459,1343,1344,1349,1353,1357,1362,1367,1371],{"__ignoreMap":457},[462,1345,1346],{"class":464,"line":465},[462,1347,1348],{},"public class MainGuiceServletContextListener extends GuiceServletContextListener {\n",[462,1350,1351],{"class":464,"line":471},[462,1352,475],{"emptyLinePlaceholder":474},[462,1354,1355],{"class":464,"line":478},[462,1356,1107],{},[462,1358,1359],{"class":464,"line":484},[462,1360,1361],{},"    protected Injector getInjector() {\n",[462,1363,1364],{"class":464,"line":489},[462,1365,1366],{},"        return Guice.createInjector(new MainGuiceModule());\n",[462,1368,1369],{"class":464,"line":495},[462,1370,702],{},[462,1372,1373],{"class":464,"line":501},[462,1374,811],{},[426,1376,1377],{},"Resztą tzn. pobieraniem instancji z injectora zajmie się specjalnie przygotowany przez nas w web.xml filtr:",[452,1379,1381],{"className":454,"code":1380,"language":456,"meta":457,"style":457},"  \u003Cfilter>\n    \u003Cfilter-name>guiceFilter\u003C\u002Ffilter-name>\n    \u003Cfilter-class>com.google.inject.servlet.GuiceFilter\u003C\u002Ffilter-class>\n  \u003C\u002Ffilter>\n\n  \u003Cfilter-mapping>\n    \u003Cfilter-name>guiceFilter\u003C\u002Ffilter-name>\n    \u003Curl-pattern>\u002F*\u003C\u002Furl-pattern>\n  \u003C\u002Ffilter-mapping>\n",[459,1382,1383,1388,1393,1398,1403,1407,1412,1416,1421],{"__ignoreMap":457},[462,1384,1385],{"class":464,"line":465},[462,1386,1387],{},"  \u003Cfilter>\n",[462,1389,1390],{"class":464,"line":471},[462,1391,1392],{},"    \u003Cfilter-name>guiceFilter\u003C\u002Ffilter-name>\n",[462,1394,1395],{"class":464,"line":478},[462,1396,1397],{},"    \u003Cfilter-class>com.google.inject.servlet.GuiceFilter\u003C\u002Ffilter-class>\n",[462,1399,1400],{"class":464,"line":484},[462,1401,1402],{},"  \u003C\u002Ffilter>\n",[462,1404,1405],{"class":464,"line":489},[462,1406,475],{"emptyLinePlaceholder":474},[462,1408,1409],{"class":464,"line":495},[462,1410,1411],{},"  \u003Cfilter-mapping>\n",[462,1413,1414],{"class":464,"line":501},[462,1415,1392],{},[462,1417,1418],{"class":464,"line":506},[462,1419,1420],{},"    \u003Curl-pattern>\u002F*\u003C\u002Furl-pattern>\n",[462,1422,1423],{"class":464,"line":512},[462,1424,1425],{},"  \u003C\u002Ffilter-mapping>\n",[426,1427,1428],{},"Jest to następna sztuczka wykorzystywana przez Guice’a. Gdybyśmy nie wykorzystali filtra każdorazowo gdy żądamy zawartości serwleta zostałaby stworzona instancja serwleta uruchomiona i zwrócony efekt jego przetwarzania. Natomiast wykorzystując filtr jesteśmy w stanie do wybranych (najczęściej dla wszystkich) serwletów wstrzyknąć odpowiednie zależności konfiguracyjne.",[426,1430,1431],{},"Konfigurując moduł w następujący sposób mapujemy wywołanie adresu: \u002Fexamplexmlrpc z ExampleRpcImpl.class:",[452,1433,1435],{"className":598,"code":1434,"language":600,"meta":457,"style":457},"public class GuiceModule extends ServletModule{\n\n    @Override\n    protected void configureServlets() {\n        super.configureServlets();\n        serve(\"\u002Fexamplerpc\").with(ExampleRpcImpl.class);\n\n    }\n}\n",[459,1436,1437,1442,1446,1450,1455,1460,1465,1469,1473],{"__ignoreMap":457},[462,1438,1439],{"class":464,"line":465},[462,1440,1441],{},"public class GuiceModule extends ServletModule{\n",[462,1443,1444],{"class":464,"line":471},[462,1445,475],{"emptyLinePlaceholder":474},[462,1447,1448],{"class":464,"line":478},[462,1449,1107],{},[462,1451,1452],{"class":464,"line":484},[462,1453,1454],{},"    protected void configureServlets() {\n",[462,1456,1457],{"class":464,"line":489},[462,1458,1459],{},"        super.configureServlets();\n",[462,1461,1462],{"class":464,"line":495},[462,1463,1464],{},"        serve(\"\u002Fexamplerpc\").with(ExampleRpcImpl.class);\n",[462,1466,1467],{"class":464,"line":501},[462,1468,475],{"emptyLinePlaceholder":474},[462,1470,1471],{"class":464,"line":506},[462,1472,702],{},[462,1474,1475],{"class":464,"line":512},[462,1476,811],{},[426,1478,1479],{},"Jest to dokładnie odpowiednik wpisu w web.xml:",[452,1481,1483],{"className":454,"code":1482,"language":456,"meta":457,"style":457},"    \u003Cservlet>\n        \u003Cservlet-name>ExampleRpc\u003C\u002Fservlet-name>\n        \u003Cservlet-class>pl.testing.server.ExampleRpcImpl\u003C\u002Fservlet-class>\n    \u003C\u002Fservlet>\n    \u003Cservlet-mapping>\n        \u003Cservlet-name>ExampleRpc\u003C\u002Fservlet-name>\n        \u003Curl-pattern>\u002Fpl.testing.Main\u002Fexamplerpc\u003C\u002Furl-pattern>\n    \u003C\u002Fservlet-mapping>\n",[459,1484,1485,1490,1495,1500,1505,1510,1514,1519],{"__ignoreMap":457},[462,1486,1487],{"class":464,"line":465},[462,1488,1489],{},"    \u003Cservlet>\n",[462,1491,1492],{"class":464,"line":471},[462,1493,1494],{},"        \u003Cservlet-name>ExampleRpc\u003C\u002Fservlet-name>\n",[462,1496,1497],{"class":464,"line":478},[462,1498,1499],{},"        \u003Cservlet-class>pl.testing.server.ExampleRpcImpl\u003C\u002Fservlet-class>\n",[462,1501,1502],{"class":464,"line":484},[462,1503,1504],{},"    \u003C\u002Fservlet>\n",[462,1506,1507],{"class":464,"line":489},[462,1508,1509],{},"    \u003Cservlet-mapping>\n",[462,1511,1512],{"class":464,"line":495},[462,1513,1494],{},[462,1515,1516],{"class":464,"line":501},[462,1517,1518],{},"        \u003Curl-pattern>\u002Fpl.testing.Main\u002Fexamplerpc\u003C\u002Furl-pattern>\n",[462,1520,1521],{"class":464,"line":506},[462,1522,1523],{},"    \u003C\u002Fservlet-mapping>\n",[426,1525,1526],{},"Dzięki powyższemu zastąpieniu uzyskujemy zdecydowanie bardziej przyjazną konfigurację programiście. Dzięki temu rozwiązaniu możemy wykorzystać pełen potencjał naszego IDE i zapisywać bezbłędnie konfigurację przy pomocy autosugestii. W podobny sposób możemy nie tylko mapować serwlety, ale również i filtry. W praktyce większość konfiguracji może zostać przeniesiona z web.xml-a do odpowiednich modułów Guice-a. Na tym jednak nie koniec. Obecny stan wymaga podczas tworzenia połączenia GwtRpc następującego zapisu:",[426,1528,1529],{},"Część kliencka:",[452,1531,1533],{"className":598,"code":1532,"language":600,"meta":457,"style":457},"@RemoteServiceRelativePath(\"..\u002Fexamplerpc\")\npublic interface ExampleRpc extends RemoteService {\n    public String myMethod(String s);\n}\n\npublic interface ExampleRpcAsync {\n    public void myMethod(String s, AsyncCallback\u003CString> callback);\n}\n",[459,1534,1535,1540,1545,1550,1554,1558,1563,1568],{"__ignoreMap":457},[462,1536,1537],{"class":464,"line":465},[462,1538,1539],{},"@RemoteServiceRelativePath(\"..\u002Fexamplerpc\")\n",[462,1541,1542],{"class":464,"line":471},[462,1543,1544],{},"public interface ExampleRpc extends RemoteService {\n",[462,1546,1547],{"class":464,"line":478},[462,1548,1549],{},"    public String myMethod(String s);\n",[462,1551,1552],{"class":464,"line":484},[462,1553,811],{},[462,1555,1556],{"class":464,"line":489},[462,1557,475],{"emptyLinePlaceholder":474},[462,1559,1560],{"class":464,"line":495},[462,1561,1562],{},"public interface ExampleRpcAsync {\n",[462,1564,1565],{"class":464,"line":501},[462,1566,1567],{},"    public void myMethod(String s, AsyncCallback\u003CString> callback);\n",[462,1569,1570],{"class":464,"line":506},[462,1571,811],{},[426,1573,1574],{},"I część serwerowa:",[452,1576,1578],{"className":598,"code":1577,"language":600,"meta":457,"style":457},"@Singleton\npublic class ExampleRpcImpl extends RemoteServiceServlet implements ExampleRpc {\n    public String myMethod(String s) {\n        return \"Server says: \" + s;\n    }\n}\n",[459,1579,1580,1585,1590,1595,1600,1604],{"__ignoreMap":457},[462,1581,1582],{"class":464,"line":465},[462,1583,1584],{},"@Singleton\n",[462,1586,1587],{"class":464,"line":471},[462,1588,1589],{},"public class ExampleRpcImpl extends RemoteServiceServlet implements ExampleRpc {\n",[462,1591,1592],{"class":464,"line":478},[462,1593,1594],{},"    public String myMethod(String s) {\n",[462,1596,1597],{"class":464,"line":484},[462,1598,1599],{},"        return \"Server says: \" + s;\n",[462,1601,1602],{"class":464,"line":489},[462,1603,702],{},[462,1605,1606],{"class":464,"line":495},[462,1607,811],{},[426,1609,1610,1611],{},"Jak widać w synchronicznym interfejsie nadal występuje niebezpieczeństwo pomyłki i konieczności zapamiętywania mapowania:\n",[459,1612,1613],{},"@RemoteServiceRelativePath(“..\u002Fexamplerpc”)",[426,1615,1616],{},"Dzięki kolejnej sztuczce wyeliminujemy i ten “boilerplate code” – kod narażony\u002Fnarażający na pomyłki. Dodajemy w części serwerowej klasę:",[452,1618,1620],{"className":598,"code":1619,"language":600,"meta":457,"style":457},"@Singleton\npublic class GuiceRemoteServiceServlet extends RemoteServiceServlet {\n\n    @Inject\n    private Injector injector;\n\n    @Override\n    public String processCall(String payload) throws SerializationException {\n        try {\n            RPCRequest req = RPC.decodeRequest(payload, null, this);\n            RemoteService service = (RemoteService) injector.getInstance(req.getMethod().getDeclaringClass());\n            return RPC.invokeAndEncodeResponse(service, req.getMethod(), req.getParameters(), req.getSerializationPolicy());\n        } catch (IncompatibleRemoteServiceException ex) {\n            log(\"IncompatibleRemoteServiceException in the processCall(String) method.\", ex);\n            return RPC.encodeResponseForFailure(null, ex);\n        }\n    }\n}\n",[459,1621,1622,1626,1631,1635,1640,1645,1649,1653,1658,1663,1668,1673,1678,1683,1688,1693,1697,1701],{"__ignoreMap":457},[462,1623,1624],{"class":464,"line":465},[462,1625,1584],{},[462,1627,1628],{"class":464,"line":471},[462,1629,1630],{},"public class GuiceRemoteServiceServlet extends RemoteServiceServlet {\n",[462,1632,1633],{"class":464,"line":478},[462,1634,475],{"emptyLinePlaceholder":474},[462,1636,1637],{"class":464,"line":484},[462,1638,1639],{},"    @Inject\n",[462,1641,1642],{"class":464,"line":489},[462,1643,1644],{},"    private Injector injector;\n",[462,1646,1647],{"class":464,"line":495},[462,1648,475],{"emptyLinePlaceholder":474},[462,1650,1651],{"class":464,"line":501},[462,1652,1107],{},[462,1654,1655],{"class":464,"line":506},[462,1656,1657],{},"    public String processCall(String payload) throws SerializationException {\n",[462,1659,1660],{"class":464,"line":512},[462,1661,1662],{},"        try {\n",[462,1664,1665],{"class":464,"line":518},[462,1666,1667],{},"            RPCRequest req = RPC.decodeRequest(payload, null, this);\n",[462,1669,1670],{"class":464,"line":524},[462,1671,1672],{},"            RemoteService service = (RemoteService) injector.getInstance(req.getMethod().getDeclaringClass());\n",[462,1674,1675],{"class":464,"line":530},[462,1676,1677],{},"            return RPC.invokeAndEncodeResponse(service, req.getMethod(), req.getParameters(), req.getSerializationPolicy());\n",[462,1679,1680],{"class":464,"line":536},[462,1681,1682],{},"        } catch (IncompatibleRemoteServiceException ex) {\n",[462,1684,1685],{"class":464,"line":542},[462,1686,1687],{},"            log(\"IncompatibleRemoteServiceException in the processCall(String) method.\", ex);\n",[462,1689,1690],{"class":464,"line":547},[462,1691,1692],{},"            return RPC.encodeResponseForFailure(null, ex);\n",[462,1694,1695],{"class":464,"line":553},[462,1696,1077],{},[462,1698,1699],{"class":464,"line":558},[462,1700,702],{},[462,1702,1703],{"class":464,"line":564},[462,1704,811],{},[426,1706,1707],{},"Jest to pośredniczący serwlet, dzięki któremu mapowanie urla na klasę serwleta zostanie zastąpione na bardzo dobrze znane i lubiane mapowanie konfiguracyjne tj. interfejsu na jego implementację. Rozwiązanie to zaproponował Eric Burke na łamach swojego bloga, które zdobyło ogromne uznanie wśród developerów GWT. W naszym przypadku osiągnęliśmy bardzo ciekawy efekt, mianowicie mapujemy interfej będący elementem części klienckiej na implementację serwerową.",[426,1709,1710],{},"Nasz plik konfiguracyjny w tym momencie wygląda następująco:",[452,1712,1714],{"className":598,"code":1713,"language":600,"meta":457,"style":457},"public class GuiceModule extends ServletModule{\n\n    @Override\n    protected void configureServlets() {\n        super.configureServlets();\n        serve(\"\u002FGWT.rpc\").with(GuiceRemoteServiceServlet.class);\n        bind(ExampleRpc.class).to(ExampleRpcImpl.class);\n    }\n}\n",[459,1715,1716,1720,1724,1728,1732,1736,1741,1746,1750],{"__ignoreMap":457},[462,1717,1718],{"class":464,"line":465},[462,1719,1441],{},[462,1721,1722],{"class":464,"line":471},[462,1723,475],{"emptyLinePlaceholder":474},[462,1725,1726],{"class":464,"line":478},[462,1727,1107],{},[462,1729,1730],{"class":464,"line":484},[462,1731,1454],{},[462,1733,1734],{"class":464,"line":489},[462,1735,1459],{},[462,1737,1738],{"class":464,"line":495},[462,1739,1740],{},"        serve(\"\u002FGWT.rpc\").with(GuiceRemoteServiceServlet.class);\n",[462,1742,1743],{"class":464,"line":501},[462,1744,1745],{},"        bind(ExampleRpc.class).to(ExampleRpcImpl.class);\n",[462,1747,1748],{"class":464,"line":506},[462,1749,702],{},[462,1751,1752],{"class":464,"line":512},[462,1753,811],{},[426,1755,1756],{},"Jak widać obsługujemy “\u002FGWT.rpc” za pomocą GuiceRemoteServiceServlet.class, który jest tak naprawdę naszym dispatcherem, czyli klasą delegującą. Oznacza to, że GuiceRemoteServiceServlet.class kontroluje ruch. Gdy po stronie klienckiej zostanie wywołany serwlet za pomocą urla: “\u002FGWT.rpc” zostanie wywołany właśnie nasz dispatcher. Wywołanie jest dekodowane:",[452,1758,1760],{"className":598,"code":1759,"language":600,"meta":457,"style":457},"RPCRequest req = RPC.decodeRequest(payload, null, this);\n",[459,1761,1762],{"__ignoreMap":457},[462,1763,1764],{"class":464,"line":465},[462,1765,1759],{},[426,1767,1768],{},"a następnie pobierana jest klasa wywołująca servlet:",[452,1770,1772],{"className":598,"code":1771,"language":600,"meta":457,"style":457},"req.getMethod().getDeclaringClass()\n",[459,1773,1774],{"__ignoreMap":457},[462,1775,1776],{"class":464,"line":465},[462,1777,1771],{},[426,1779,1780],{},"na podstawie której poprzez Injector otrzymujemy RemoteService, czyli klasę, z której musi dziedziczyć każdy servlet obsługujący GwtRPC. W naszym przypadku będzie to klasa, którą zbindowaliśmy z klasą wywołującą request. Dalsze linijki polegają na obsłudze samego wywołania oraz na zwróceniu odpowiedzi… ot i cała magia.\nNależy pamiętać, że w części klienckiej będziemy używać teraz za każdym razem adnotacji aby wszystko chodziło jak należy:",[452,1782,1784],{"className":598,"code":1783,"language":600,"meta":457,"style":457},"@RemoteServiceRelativePath(\"..\u002FGWT.rpc\")\n",[459,1785,1786],{"__ignoreMap":457},[462,1787,1788],{"class":464,"line":465},[462,1789,1783],{},[426,1791,1792],{},"Dzięki zastosowaniu powyższej metody otrzymaliśmy mechanizm, który pozwoli na klarowne bo nie w xml-u oraz bezpieczne pisanie konfiguracji w oparciu o autosugestie. Ponadto jest on idealnym wstępem do stworzenia modularnej części serwerowej aplikacji wykorzystującej GWT, ale o tym dowiecie się z przyszłych postów.",[426,1794,1795],{},"Podsumowując konfigurację Guice-a powinniśmy otrzymać przykładowy zestaw klas po stronie klienckiej:",[452,1797,1799],{"className":598,"code":1798,"language":600,"meta":457,"style":457},"@RemoteServiceRelativePath(\"..\u002FGWT.rpc\")\npublic interface ExampleRpc extends RemoteService {\n    public String myMethod(String s);\n}\n\npublic interface ExampleRpcAsync {\n    public void myMethod(String s, AsyncCallback\u003CString> callback);\n}\n",[459,1800,1801,1805,1809,1813,1817,1821,1825,1829],{"__ignoreMap":457},[462,1802,1803],{"class":464,"line":465},[462,1804,1783],{},[462,1806,1807],{"class":464,"line":471},[462,1808,1544],{},[462,1810,1811],{"class":464,"line":478},[462,1812,1549],{},[462,1814,1815],{"class":464,"line":484},[462,1816,811],{},[462,1818,1819],{"class":464,"line":489},[462,1820,475],{"emptyLinePlaceholder":474},[462,1822,1823],{"class":464,"line":495},[462,1824,1562],{},[462,1826,1827],{"class":464,"line":501},[462,1828,1567],{},[462,1830,1831],{"class":464,"line":506},[462,1832,811],{},[426,1834,1835],{},"oraz zestaw plików po stronie serwerowej:",[426,1837,1838],{},"web.xml:",[452,1840,1842],{"className":454,"code":1841,"language":456,"meta":457,"style":457},"\u003C?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\u003Cweb-app version=\"2.5\" xmlns=\"http:\u002F\u002Fjava.sun.com\u002Fxml\u002Fns\u002Fjavaee\" xmlns:xsi=\"http:\u002F\u002Fwww.w3.org\u002F2001\u002FXMLSchema-instance\" xsi:schemaLocation=\"http:\u002F\u002Fjava.sun.com\u002Fxml\u002Fns\u002Fjavaee http:\u002F\u002Fjava.sun.com\u002Fxml\u002Fns\u002Fjavaee\u002Fweb-app_2_5.xsd\">\n    \u003Clistener>\n        \u003Clistener-class>pl.testing.server.GuiceConfig\u003C\u002Flistener-class>\n    \u003C\u002Flistener>\n    \u003Cfilter>\n        \u003Cfilter-name>guiceFilter\u003C\u002Ffilter-name>\n        \u003Cfilter-class>com.google.inject.servlet.GuiceFilter\u003C\u002Ffilter-class>\n    \u003C\u002Ffilter>\n    \u003Cfilter-mapping>\n        \u003Cfilter-name>guiceFilter\u003C\u002Ffilter-name>\n        \u003Curl-pattern>\u002F*\u003C\u002Furl-pattern>\n    \u003C\u002Ffilter-mapping>\n    \u003Csession-config>\n        \u003Csession-timeout>\n            30\n        \u003C\u002Fsession-timeout>\n    \u003C\u002Fsession-config>\n    \u003Cwelcome-file-list>\n        \u003Cwelcome-file>welcomeGWT.html\u003C\u002Fwelcome-file>\n    \u003C\u002Fwelcome-file-list>\n\u003C\u002Fweb-app>\n",[459,1843,1844,1848,1852,1857,1862,1867,1872,1877,1882,1887,1892,1896,1901,1906,1910,1914,1918,1922,1926,1930,1934,1938],{"__ignoreMap":457},[462,1845,1846],{"class":464,"line":465},[462,1847,468],{},[462,1849,1850],{"class":464,"line":471},[462,1851,921],{},[462,1853,1854],{"class":464,"line":478},[462,1855,1856],{},"    \u003Clistener>\n",[462,1858,1859],{"class":464,"line":484},[462,1860,1861],{},"        \u003Clistener-class>pl.testing.server.GuiceConfig\u003C\u002Flistener-class>\n",[462,1863,1864],{"class":464,"line":489},[462,1865,1866],{},"    \u003C\u002Flistener>\n",[462,1868,1869],{"class":464,"line":495},[462,1870,1871],{},"    \u003Cfilter>\n",[462,1873,1874],{"class":464,"line":501},[462,1875,1876],{},"        \u003Cfilter-name>guiceFilter\u003C\u002Ffilter-name>\n",[462,1878,1879],{"class":464,"line":506},[462,1880,1881],{},"        \u003Cfilter-class>com.google.inject.servlet.GuiceFilter\u003C\u002Ffilter-class>\n",[462,1883,1884],{"class":464,"line":512},[462,1885,1886],{},"    \u003C\u002Ffilter>\n",[462,1888,1889],{"class":464,"line":518},[462,1890,1891],{},"    \u003Cfilter-mapping>\n",[462,1893,1894],{"class":464,"line":524},[462,1895,1876],{},[462,1897,1898],{"class":464,"line":530},[462,1899,1900],{},"        \u003Curl-pattern>\u002F*\u003C\u002Furl-pattern>\n",[462,1902,1903],{"class":464,"line":536},[462,1904,1905],{},"    \u003C\u002Ffilter-mapping>\n",[462,1907,1908],{"class":464,"line":542},[462,1909,926],{},[462,1911,1912],{"class":464,"line":547},[462,1913,931],{},[462,1915,1916],{"class":464,"line":553},[462,1917,936],{},[462,1919,1920],{"class":464,"line":558},[462,1921,941],{},[462,1923,1924],{"class":464,"line":564},[462,1925,946],{},[462,1927,1928],{"class":464,"line":693},[462,1929,951],{},[462,1931,1932],{"class":464,"line":699},[462,1933,956],{},[462,1935,1936],{"class":464,"line":705},[462,1937,961],{},[462,1939,1940],{"class":464,"line":710},[462,1941,966],{},[452,1943,1945],{"className":598,"code":1944,"language":600,"meta":457,"style":457},"public class GuiceConfig extends GuiceServletContextListener {\n\n    @Override\n    protected Injector getInjector() {\n        return Guice.createInjector(new GuiceModule());\n    }\n}\n\npublic class GuiceModule extends ServletModule{\n\n    @Override\n    protected void configureServlets() {\n        super.configureServlets();\n        serve(\"\u002FGWT.rpc\").with(GuiceRemoteServiceServlet.class);\n        bind(ExampleRpc.class).to(ExampleRpcImpl.class);\n    }\n}\n\npublic class ExampleRpcImpl extends RemoteServiceServlet implements ExampleRpc {\n    public String myMethod(String s) {\n        return \"Server says: \" + s;\n    }\n}\n\n@Singleton\npublic class GuiceRemoteServiceServlet extends RemoteServiceServlet {\n\n    @Inject\n    private Injector injector;\n\n    @Override\n    public String processCall(String payload) throws SerializationException {\n        try {\n            RPCRequest req = RPC.decodeRequest(payload, null, this);\n            RemoteService service = (RemoteService) injector.getInstance(req.getMethod().getDeclaringClass());\n            return RPC.invokeAndEncodeResponse(service, req.getMethod(), req.getParameters(), req.getSerializationPolicy());\n        } catch (IncompatibleRemoteServiceException ex) {\n            log(\"IncompatibleRemoteServiceException in the processCall(String) method.\", ex);\n            return RPC.encodeResponseForFailure(null, ex);\n        }\n    }\n}\n",[459,1946,1947,1952,1956,1960,1964,1969,1973,1977,1981,1985,1989,1993,1997,2001,2005,2009,2013,2017,2021,2025,2029,2033,2037,2041,2045,2049,2053,2057,2061,2065,2069,2073,2077,2081,2085,2089,2093,2097,2101,2105,2110,2115],{"__ignoreMap":457},[462,1948,1949],{"class":464,"line":465},[462,1950,1951],{},"public class GuiceConfig extends GuiceServletContextListener {\n",[462,1953,1954],{"class":464,"line":471},[462,1955,475],{"emptyLinePlaceholder":474},[462,1957,1958],{"class":464,"line":478},[462,1959,1107],{},[462,1961,1962],{"class":464,"line":484},[462,1963,1361],{},[462,1965,1966],{"class":464,"line":489},[462,1967,1968],{},"        return Guice.createInjector(new GuiceModule());\n",[462,1970,1971],{"class":464,"line":495},[462,1972,702],{},[462,1974,1975],{"class":464,"line":501},[462,1976,811],{},[462,1978,1979],{"class":464,"line":506},[462,1980,475],{"emptyLinePlaceholder":474},[462,1982,1983],{"class":464,"line":512},[462,1984,1441],{},[462,1986,1987],{"class":464,"line":518},[462,1988,475],{"emptyLinePlaceholder":474},[462,1990,1991],{"class":464,"line":524},[462,1992,1107],{},[462,1994,1995],{"class":464,"line":530},[462,1996,1454],{},[462,1998,1999],{"class":464,"line":536},[462,2000,1459],{},[462,2002,2003],{"class":464,"line":542},[462,2004,1740],{},[462,2006,2007],{"class":464,"line":547},[462,2008,1745],{},[462,2010,2011],{"class":464,"line":553},[462,2012,702],{},[462,2014,2015],{"class":464,"line":558},[462,2016,811],{},[462,2018,2019],{"class":464,"line":564},[462,2020,475],{"emptyLinePlaceholder":474},[462,2022,2023],{"class":464,"line":693},[462,2024,1589],{},[462,2026,2027],{"class":464,"line":699},[462,2028,1594],{},[462,2030,2031],{"class":464,"line":705},[462,2032,1599],{},[462,2034,2035],{"class":464,"line":710},[462,2036,702],{},[462,2038,2039],{"class":464,"line":715},[462,2040,811],{},[462,2042,2043],{"class":464,"line":721},[462,2044,475],{"emptyLinePlaceholder":474},[462,2046,2047],{"class":464,"line":727},[462,2048,1584],{},[462,2050,2051],{"class":464,"line":732},[462,2052,1630],{},[462,2054,2055],{"class":464,"line":738},[462,2056,475],{"emptyLinePlaceholder":474},[462,2058,2059],{"class":464,"line":744},[462,2060,1639],{},[462,2062,2063],{"class":464,"line":750},[462,2064,1644],{},[462,2066,2067],{"class":464,"line":756},[462,2068,475],{"emptyLinePlaceholder":474},[462,2070,2071],{"class":464,"line":762},[462,2072,1107],{},[462,2074,2075],{"class":464,"line":768},[462,2076,1657],{},[462,2078,2079],{"class":464,"line":774},[462,2080,1662],{},[462,2082,2083],{"class":464,"line":780},[462,2084,1667],{},[462,2086,2087],{"class":464,"line":786},[462,2088,1672],{},[462,2090,2091],{"class":464,"line":791},[462,2092,1677],{},[462,2094,2095],{"class":464,"line":797},[462,2096,1682],{},[462,2098,2099],{"class":464,"line":803},[462,2100,1687],{},[462,2102,2103],{"class":464,"line":808},[462,2104,1692],{},[462,2106,2108],{"class":464,"line":2107},40,[462,2109,1077],{},[462,2111,2113],{"class":464,"line":2112},41,[462,2114,702],{},[462,2116,2118],{"class":464,"line":2117},42,[462,2119,811],{},[426,2121,2122],{},"W tym miejscu zakończyliśmy konfigurację Guice-a wraz z GWT. W następnej części zajmiemy się obsługą Hibernate.",[984,2124,986],{},{"title":457,"searchDepth":471,"depth":471,"links":2126},[],"2010-10-15","Instalacja, konfiguracja oraz zestawienie z Google Web Toolkit (in Polish)",{"layout":993},"\u002Fblog\u002F2010-12-15-gwt-and-guice",{"title":1000,"description":2128},"2.blog\u002F2010-12-15-gwt-and-guice","jLZT8dfB96shZTFJi08TjTQJjya4l4av4GLdxf8ATsg",{"id":2135,"title":2136,"authors":409,"badge":409,"body":2137,"date":2521,"description":2522,"extension":991,"image":409,"meta":2523,"navigation":474,"path":2524,"seo":2525,"stem":2526,"__hash__":2527},"posts\u002F2.blog\u002F2010-12-16-hiberante-with-guice.md","Hibernate + Guice",{"type":423,"value":2138,"toc":2519},[2139,2142,2145,2148,2151,2154,2232,2235,2451,2454,2483,2490,2493,2502,2505,2514,2517],[426,2140,2141],{},"Hibernate – framework do realizacji warstwy dostępu do danych (ang. persistance layer). Zapewnia on przede wszystkim translację danych pomiędzy relacyjną bazą danych, a światem obiektowym (ang. O\u002FR mapping). Opiera się na wykorzystaniu opisu struktury danych za pomocą języka XML, dzięki czemu można “rzutować” obiekty, stosowane w obiektowych językach programowania, takich jak Java bezpośrednio na istniejące tabele bazy danych. Dodatkowo Hibernate zwiększa wydajność operacji na bazie danych dzięki buforowaniu i minimalizacji liczby przesyłanych zapytań. Jest to projekt rozwijany jako open source. (wikipedia.pl)",[426,2143,2144],{},"Hibernate jest kolejnym wyborem naszych specjalistów w kwestii wyboru podstawowych komponentów do tworzenia aplikacji. Jest to najpopularniejszy, najbardziej zaawansowany ORM na rynku. Pomimo jego silnej pozycji chcemy zaznaczyć, że w bardziej zaawansowanych projektach dodatkowo posiłkujemy się MyBatisem, który stanowi doskonałe uzupełnienie bo raczej nie konkurencję :).",[426,2146,2147],{},"Kolejną kwestią, którą należy poruszyć jest to czy używać Hibernate bezpośrednio, czy jako dostawcy JPA. JPA jest jedynie standardem opisanym przez Sun-a i stanowi jedynie interfejs dostępu do danych. Oznacza to, że korzystając z interfejsów JPA podczas pobierania, wyszukiwania czy utrwalania obiektów korzystamy z interfejsu JPA. To co się faktycznie dzieje za kulisami, czyli w jaki sposób komunikacja z bazą się odbywa wykonuje już dostawca usługi ORM, czyli implementacja interfejsu JPA. Najpopularniejszymi implementacjami są: Hibernate, TopLink, Kodo, czy OpenJPA. Tak więc podczas pracy z bazą danych poprzez JPA nie musimy wiedzieć z jakiego mechanizmu obecnie korzystamy. Można to zobrazować do samochodu z silnikiem, bądź komputera i procesora. Silnik i procesor można wymienić na każdy inny pasujący do interfejsu. Nowe elementy spełniają identyczną rolę co ich poprzednicy natomiast swoim działaniem oraz efektami np mocy czy mocy obliczeniowej mogą się różnić od poprzedników. Z interfejsem JPA jest podobnie. JPA jest jak rama samochodu bądź gniazdo procesora – można do niego zainstalować elementy, które będą wykonywały określone czynności ale to urządzenie musi łączyć się ze środowiskiem zewnętrznym w okreslony przez interfejs sposób.\nJest to bardzo ciekawe rozwiązanie, które pozwoli na zastosowanie podzespołu według swoich preferencji. Dzięki wykorzystywaniu JPA w dowolnym momencie możemy wymienić Hibernate na np. TopLink-a. Rzeczywistość niestety nie jest taka różowa jakby się mogło wydawać. JPA jest specyfikacją, która oczywiście ulega ciągłym modyfikacjom (JPA 1.0 -> JPA 2.0), jednak dostawcy ORM oprócz implementacji JPA znacznie poszerzają swoje możliwości idące daleko poza interfejs. Czynnikiem decydującym o rezygnacji z JPA była konfiguracja dostawcy, która nie mogła zostać zdefiniowana dynamicznie a tylko poprzez plik persistance.xml. Ponieważ dążymy do modułowej budowy aplikacji był to niezbędny element. Jako producenci płyty głównej zrezygnowaliśmy ze standardowego gniazda, przez które nie możemy obsłużyć dodatkowych 2 rdzeni procesora. Ponosimy ryzyko, że gdy będziemy chcieli zaktualizować Hibernate-a możemy napotkać problemy ze zgodnością niektórych klas, bądź obsłużyć w sposób wspomagany transakcję ale rzucając na szali liczne możliwości, ułatwienia oraz spełnienia wszystkich wymagań jakie stawialiśmy aplikacji decydujemy się zrezygnować z JPA.",[426,2149,2150],{},"Po nieco przydługawym wstępie pora rozpocząć prace z Hibernate. Jak wspomnieliśmy zależy nam na programowalnej konfiguracji a dokładniej na programowalnym dodawaniu plików z mapowaniami. W tym miejscu ponownie wyprzedzimy nieco wątek. Coraz popularniejszym sposobem definiowania mapowań czy to przez JPA czy przez dostawców jest umieszczanie adnotacji bezpośrednio w klasie domenowej co ma ułatwić, przyspieszyć pracę oraz zmniejszyć ilość kodu. Gdy konfigurowaliśmy Guice-a uciekaliśmy od xml-a właśnie w adnotacje tak tutaj niestety musimy zrobić krok w tył aby wyjść z zaułka do którego byśmy trafili zakładając dalsze wykorzystywanie w naszym projekcie GWT.\nPodczas opisu frameworka GWT wspominaliśmy jakie ograniczenia są nałożone na warstwę kliencką. Klasy domenowe, które umieszczone są w części klienckiej mogą być wykorzystywane w części klienckiej, podczas transportowania danych między częścią kliencką a serwerową w mechaniźmie RPC oraz w części serwerowej. Dodając jednak adnotacje czy to Hibernate-owe, czy to JPA dodajemy fragmenty bibliotek niezgodnych z emulowanym środowiskiem GWT. Tym samym takich klas nie będziemy mogli wykorzystać ani w części klienckiej ani w transporcie GWT-RPC.\nJest to dość poważne ograniczenie ponieważ nie ma łatwego sposobu na obejście tego problemu. Jednym ze sposobów jest rezygnacja z adnotacji i wykorzystanie mapowań w XM-u, bądź można napisać klon naszej klasy domenowej, w niej dodać adnotacje a gdy zajdzie potrzeba przesłania danych czy to na stronę kliencką czy z klienckiej do bazy należałoby dane przekazać pomiędzy tymi plikami. Jest to podejście gdzie klon klasy domenowej wykorzystujący adnotacje nazywa się DTO. Istnieją oczywiście dodatkowe biblioteki takie jak Dozzer, które wspomagają pracę z DTO. Biblioteka ta na podstawie mapowania atrybutów jednej klasy do drugiej pozwala na niemal zautomatyzowany proces przepływu danych między obiektami. Niestety podejście DTO sprawia, że potrzebna jest masa dodatkowego kodu w którym również mogą pojawić się błędy a refaktoryzacja czy optymalizacja jest w tym przypadku niezwykle utrudniona, dlatego koncept adnotacji również został przez nas odrzucony. Więcej informacji na temat wspomnianych rozwiązań można znaleźć tu",[426,2152,2153],{},"Załóżmy, że będziemy uwierzytelniać następującą klasę domenową:",[452,2155,2157],{"className":598,"code":2156,"language":600,"meta":457,"style":457},"public class Person {\n    Long id;\n    String login;\n    String password;\n    String displayName;\n    Date registrationDate;\n    Date lastLoginDate;\n    Integer version;\n\n    \u002F\u002Fgetters and setters\n\n    @Override\n    public String toString() {\n        return \"Person{\" + \"id=\" + id + \",login=\" + login + \",password=\" + password + \",displayName=\" + displayName + \",registrationDate=\" + registrationDate + \",lastLoginDate=\" + lastLoginDate + \",version=\" + version + '}';\n    }\n}\n",[459,2158,2159,2163,2168,2173,2178,2183,2188,2193,2198,2202,2207,2211,2215,2219,2224,2228],{"__ignoreMap":457},[462,2160,2161],{"class":464,"line":465},[462,2162,1215],{},[462,2164,2165],{"class":464,"line":471},[462,2166,2167],{},"    Long id;\n",[462,2169,2170],{"class":464,"line":478},[462,2171,2172],{},"    String login;\n",[462,2174,2175],{"class":464,"line":484},[462,2176,2177],{},"    String password;\n",[462,2179,2180],{"class":464,"line":489},[462,2181,2182],{},"    String displayName;\n",[462,2184,2185],{"class":464,"line":495},[462,2186,2187],{},"    Date registrationDate;\n",[462,2189,2190],{"class":464,"line":501},[462,2191,2192],{},"    Date lastLoginDate;\n",[462,2194,2195],{"class":464,"line":506},[462,2196,2197],{},"    Integer version;\n",[462,2199,2200],{"class":464,"line":512},[462,2201,475],{"emptyLinePlaceholder":474},[462,2203,2204],{"class":464,"line":518},[462,2205,2206],{},"    \u002F\u002Fgetters and setters\n",[462,2208,2209],{"class":464,"line":524},[462,2210,475],{"emptyLinePlaceholder":474},[462,2212,2213],{"class":464,"line":530},[462,2214,1107],{},[462,2216,2217],{"class":464,"line":536},[462,2218,1283],{},[462,2220,2221],{"class":464,"line":542},[462,2222,2223],{},"        return \"Person{\" + \"id=\" + id + \",login=\" + login + \",password=\" + password + \",displayName=\" + displayName + \",registrationDate=\" + registrationDate + \",lastLoginDate=\" + lastLoginDate + \",version=\" + version + '}';\n",[462,2225,2226],{"class":464,"line":547},[462,2227,702],{},[462,2229,2230],{"class":464,"line":553},[462,2231,811],{},[426,2233,2234],{},"Plik konfiguracyjny Hibernate będzie więc wyglądał następująco zakładając, że jako silnik bazy danych wykorzystamy Derby:",[452,2236,2238],{"className":598,"code":2237,"language":600,"meta":457,"style":457},"public class GuiceConfig extends GuiceServletContextListener {\n\n    @Override\n    public void contextInitialized(ServletContextEvent servletContextEvent) {\n       super.contextInitialized(servletContextEvent);\n    }\n\n    @Override\n    protected Injector getInjector() {\n        return Guice.createInjector(new GuiceModule(), new HibernateModule());\n    }\n\n    public static void main(String[] args){\n        Injector injector = Guice.createInjector(new GuiceModule(), new HibernateModule());\n        SessionFactory sf = injector.getInstance(SessionFactory.class);\n    }\n}\n\npublic class HibernateModule extends AbstractModule {\n\n    @Override\n    protected void configure() {\n       bind(SessionFactory.class).toProvider(HibernateSessionFactoryProvider.class).in(Singleton.class);\n    }\n}\n\nclass HibernateSessionFactoryProvider implements Provider {\n\n    public SessionFactory get() {\n        Configuration configuration = new Configuration();\n        configuration.setProperty(\"hibernate.dialect\", \"org.hibernate.dialect.DerbyDialect\");\n        configuration.setProperty(\"hibernate.connection.driver_class\", \"org.apache.derby.jdbc.ClientDriver\");\n        configuration.setProperty(\"hibernate.connection.url\", \"jdbc:derby:\u002F\u002Flocalhost:1527\u002Fsample\");\n        configuration.setProperty(\"hibernate.connection.username\", \"app\");\n        configuration.setProperty(\"hibernate.connection.password\", \"app\");\n        configuration.setProperty(\"hibernate.current_session_context_class\", \"thread\");\n        configuration.setProperty(\"hibernate.cache.provider_class\", \"org.hibernate.cache.NoCacheProvider\");\n        configuration.setProperty(\"hibernate.show_sql\", \"true\");\n        configuration.setProperty(\"hibernate.hbm2ddl.auto\", \"create-drop\");\n\n        configuration.addClass(Person.class);\n\n        SessionFactory sf = configuration.buildSessionFactory();\n        return sf;\n    }\n}\n",[459,2239,2240,2244,2248,2252,2257,2262,2266,2270,2274,2278,2283,2287,2291,2296,2301,2306,2310,2314,2318,2323,2327,2331,2335,2340,2344,2348,2352,2357,2361,2366,2371,2376,2381,2386,2391,2396,2401,2406,2411,2416,2420,2425,2429,2435,2441,2446],{"__ignoreMap":457},[462,2241,2242],{"class":464,"line":465},[462,2243,1951],{},[462,2245,2246],{"class":464,"line":471},[462,2247,475],{"emptyLinePlaceholder":474},[462,2249,2250],{"class":464,"line":478},[462,2251,1107],{},[462,2253,2254],{"class":464,"line":484},[462,2255,2256],{},"    public void contextInitialized(ServletContextEvent servletContextEvent) {\n",[462,2258,2259],{"class":464,"line":489},[462,2260,2261],{},"       super.contextInitialized(servletContextEvent);\n",[462,2263,2264],{"class":464,"line":495},[462,2265,702],{},[462,2267,2268],{"class":464,"line":501},[462,2269,475],{"emptyLinePlaceholder":474},[462,2271,2272],{"class":464,"line":506},[462,2273,1107],{},[462,2275,2276],{"class":464,"line":512},[462,2277,1361],{},[462,2279,2280],{"class":464,"line":518},[462,2281,2282],{},"        return Guice.createInjector(new GuiceModule(), new HibernateModule());\n",[462,2284,2285],{"class":464,"line":524},[462,2286,702],{},[462,2288,2289],{"class":464,"line":530},[462,2290,475],{"emptyLinePlaceholder":474},[462,2292,2293],{"class":464,"line":536},[462,2294,2295],{},"    public static void main(String[] args){\n",[462,2297,2298],{"class":464,"line":542},[462,2299,2300],{},"        Injector injector = Guice.createInjector(new GuiceModule(), new HibernateModule());\n",[462,2302,2303],{"class":464,"line":547},[462,2304,2305],{},"        SessionFactory sf = injector.getInstance(SessionFactory.class);\n",[462,2307,2308],{"class":464,"line":553},[462,2309,702],{},[462,2311,2312],{"class":464,"line":558},[462,2313,811],{},[462,2315,2316],{"class":464,"line":564},[462,2317,475],{"emptyLinePlaceholder":474},[462,2319,2320],{"class":464,"line":693},[462,2321,2322],{},"public class HibernateModule extends AbstractModule {\n",[462,2324,2325],{"class":464,"line":699},[462,2326,475],{"emptyLinePlaceholder":474},[462,2328,2329],{"class":464,"line":705},[462,2330,1107],{},[462,2332,2333],{"class":464,"line":710},[462,2334,1112],{},[462,2336,2337],{"class":464,"line":715},[462,2338,2339],{},"       bind(SessionFactory.class).toProvider(HibernateSessionFactoryProvider.class).in(Singleton.class);\n",[462,2341,2342],{"class":464,"line":721},[462,2343,702],{},[462,2345,2346],{"class":464,"line":727},[462,2347,811],{},[462,2349,2350],{"class":464,"line":732},[462,2351,475],{"emptyLinePlaceholder":474},[462,2353,2354],{"class":464,"line":738},[462,2355,2356],{},"class HibernateSessionFactoryProvider implements Provider {\n",[462,2358,2359],{"class":464,"line":744},[462,2360,475],{"emptyLinePlaceholder":474},[462,2362,2363],{"class":464,"line":750},[462,2364,2365],{},"    public SessionFactory get() {\n",[462,2367,2368],{"class":464,"line":756},[462,2369,2370],{},"        Configuration configuration = new Configuration();\n",[462,2372,2373],{"class":464,"line":762},[462,2374,2375],{},"        configuration.setProperty(\"hibernate.dialect\", \"org.hibernate.dialect.DerbyDialect\");\n",[462,2377,2378],{"class":464,"line":768},[462,2379,2380],{},"        configuration.setProperty(\"hibernate.connection.driver_class\", \"org.apache.derby.jdbc.ClientDriver\");\n",[462,2382,2383],{"class":464,"line":774},[462,2384,2385],{},"        configuration.setProperty(\"hibernate.connection.url\", \"jdbc:derby:\u002F\u002Flocalhost:1527\u002Fsample\");\n",[462,2387,2388],{"class":464,"line":780},[462,2389,2390],{},"        configuration.setProperty(\"hibernate.connection.username\", \"app\");\n",[462,2392,2393],{"class":464,"line":786},[462,2394,2395],{},"        configuration.setProperty(\"hibernate.connection.password\", \"app\");\n",[462,2397,2398],{"class":464,"line":791},[462,2399,2400],{},"        configuration.setProperty(\"hibernate.current_session_context_class\", \"thread\");\n",[462,2402,2403],{"class":464,"line":797},[462,2404,2405],{},"        configuration.setProperty(\"hibernate.cache.provider_class\", \"org.hibernate.cache.NoCacheProvider\");\n",[462,2407,2408],{"class":464,"line":803},[462,2409,2410],{},"        configuration.setProperty(\"hibernate.show_sql\", \"true\");\n",[462,2412,2413],{"class":464,"line":808},[462,2414,2415],{},"        configuration.setProperty(\"hibernate.hbm2ddl.auto\", \"create-drop\");\n",[462,2417,2418],{"class":464,"line":2107},[462,2419,475],{"emptyLinePlaceholder":474},[462,2421,2422],{"class":464,"line":2112},[462,2423,2424],{},"        configuration.addClass(Person.class);\n",[462,2426,2427],{"class":464,"line":2117},[462,2428,475],{"emptyLinePlaceholder":474},[462,2430,2432],{"class":464,"line":2431},43,[462,2433,2434],{},"        SessionFactory sf = configuration.buildSessionFactory();\n",[462,2436,2438],{"class":464,"line":2437},44,[462,2439,2440],{},"        return sf;\n",[462,2442,2444],{"class":464,"line":2443},45,[462,2445,702],{},[462,2447,2449],{"class":464,"line":2448},46,[462,2450,811],{},[426,2452,2453],{},"Razem z modułem naszej aplikacji dodajemy moduł, dzięki któremu dodamy obsługę bazy danych. Moduł ten umożliwia wstrzyknięcie w dowolne miejsce aplikacji implementacji SessionFactory, która w tym przypadku jest dostarczana przez Providera. Kod możemy przetestować bez konieczności uruchamiania serwera za pomocą pseudo klasy testującej:",[452,2455,2457],{"className":598,"code":2456,"language":600,"meta":457,"style":457},"@Test\npublic void testingHibernateModule() {\n    Injector injector = Guice.createInjector(new GuiceModule(), new HibernateModule());\n    SessionFactory sf = injector.getInstance(SessionFactory.class);\n}\n",[459,2458,2459,2464,2469,2474,2479],{"__ignoreMap":457},[462,2460,2461],{"class":464,"line":465},[462,2462,2463],{},"@Test\n",[462,2465,2466],{"class":464,"line":471},[462,2467,2468],{},"public void testingHibernateModule() {\n",[462,2470,2471],{"class":464,"line":478},[462,2472,2473],{},"    Injector injector = Guice.createInjector(new GuiceModule(), new HibernateModule());\n",[462,2475,2476],{"class":464,"line":484},[462,2477,2478],{},"    SessionFactory sf = injector.getInstance(SessionFactory.class);\n",[462,2480,2481],{"class":464,"line":489},[462,2482,811],{},[426,2484,2485,2486,2489],{},"Podczas uruchamiania zostanie rzucony następujący błąd:\n",[459,2487,2488],{},"“Error in custom provider, org.hibernate.MappingNotFoundException: resource: pl\u002Ftesting\u002Fclient\u002FPerson.hbm.xml not found”",", który oznacza, że brakuje pliku mapującego.",[426,2491,2492],{},"Gdy konfigurowaliśmy Hibernate-a w linijce:",[452,2494,2496],{"className":598,"code":2495,"language":600,"meta":457,"style":457},"configuration.addClass(Person.class);\n",[459,2497,2498],{"__ignoreMap":457},[462,2499,2500],{"class":464,"line":465},[462,2501,2495],{},[426,2503,2504],{},"przyjęliśmy, że będziemy korzystać z klasy Person a zgodnie z manualem: Programmatic configuration przy zastosowaniu takiej konfiguracji będzie wymagany plik mapujący nazywający się tak jak klasa i znajdujący się w tej samej lokalizacji (paczce) co klasa mapowana:",[452,2506,2508],{"className":454,"code":2507,"language":456,"meta":457,"style":457},"\u003C!--?xml version=\"1.0\" encoding=\"UTF-8\"?-->\n",[459,2509,2510],{"__ignoreMap":457},[462,2511,2512],{"class":464,"line":465},[462,2513,2507],{},[426,2515,2516],{},"Po dodaniu pliku mapującego i uruchomieniu metody testującej schemat naszej bazy zostanie zaktualizowany a środowisko gotowe do wykorzystywania w modułowej aplikacji internetowej.",[984,2518,986],{},{"title":457,"searchDepth":471,"depth":471,"links":2520},[],"2010-12-16","Instalacja, konfiguracja oraz zestawienie z Guicem (in Polish)",{"layout":993},"\u002Fblog\u002F2010-12-16-hiberante-with-guice",{"title":2136,"description":2522},"2.blog\u002F2010-12-16-hiberante-with-guice","MfSt_kY4KA9i8P8-P_zGYwzTMsW4JdOxCrGgr2quTBE",{"id":2529,"title":2530,"authors":409,"badge":409,"body":2531,"date":2726,"description":2727,"extension":991,"image":409,"meta":2728,"navigation":474,"path":2729,"seo":2730,"stem":2731,"__hash__":2732},"posts\u002F2.blog\u002F2011-05-21-c3p0-proper-closing-application.md","C3P0 - poprawne zamykanie",{"type":423,"value":2532,"toc":2724},[2533,2536,2539,2542,2545,2553,2556,2574,2577,2722],[426,2534,2535],{},"W przypadku, gdy aplikacja do przechowywania danych wykorzystuje relacyjną bazę danych bardzo często się zdarza, że korzysta z takich narzędzi wspomagających jak Hibernate czy MyBatis (określenie “narzędzie” jest tu celowe, ponieważ najczęściej o tej warstwie mówi się skrótowo ORM, przy czym MyBatis ORM-em nie jest).",[426,2537,2538],{},"Biblioteki te (jak i również inne) mogą wykorzystywać zewnętrzne mechanizmy transakcji, czy zarządzania źródłami danych i tu zmierzam do C3P0.",[426,2540,2541],{},"C3p0 jest biblioteką, która wnosi warstwę obsługi wielu połączeń z bazą danych. W skrócie: gdy klient\u002Fusługa chce pobrać dane z bazy połączenie z bazą danych zostaje zajęte przez sesję klienta, które zwalniane jest dopiero po przetworzeniu i zwróceniu wyników. W przypadku, gdy wielu klientów chce naraz pobrać dane jeden użytkownik okupuje połączenie a pozostali czekają w kolejce dopóki się nie zwolni. Biorąc pod uwagę skalę, czyli duża ilość użytkowników korzysta z aplikacji, która wykonuje skomplikowane, powolne zapytania na dużej bazie danych może to być niewątpliwie spory problem.",[426,2543,2544],{},"C3P0 pozwala na wprowadzenie większej ilości niezależnych połączeń do bazy – taka wielowątkowość dla wątków :-).",[426,2546,2547,2548,2552],{},"Więcej informacji na ten temat można znaleźć na stronie projektu: ",[977,2549,2550],{"href":2550,"rel":2551},"http:\u002F\u002Fsourceforge.net\u002Fprojects\u002Fc3p0\u002F",[981]," bądź na stronach bibliotek wykorzystujących C3P0.",[426,2554,2555],{},"Dzisiaj jednak zgodnie z tytułem zajmiemy się problemem, który może stanowić o stabilnej pracy naszej aplikacji. Gdy już przekonamy się do korzystania z biblioteki problem pojawia się podczas undeployingu na bazie Tomcat. Biblioteka nie zamyka i wyrejestrowuje nawiązanych połączeń. Podczas próby ponownego umieszczenia projektu na serwerze mogą pojawić się problemy, ponieważ niektóre klasy pozostają w pamięci. W ostateczności może nie dojść do poprawnego umieszczenia aplikacji. Od wersji 6.9 Tomcata została zaaplikowana usługa retrospekcji dla wybranych klas, co pozwala wyrejestrować je automatycznie przez kontener, ale z doświadczenia zauważyłem, że nie dzieje się to za każdym razem. Rozwiązaniem może być ręczne pozamykanie połączeń, które wywołamy w momencie gdy serwer jest zatrzymywany. Służy do tego listener który dodajemy w web.xml:",[452,2557,2559],{"className":454,"code":2558,"language":456,"meta":457,"style":457},"\u003Clistener>\n    \u003Clistener-class>pl.xperios.rdk.server.startup.ServerStarter\u003C\u002Flistener-class>\n\u003C\u002Flistener>\n",[459,2560,2561,2565,2570],{"__ignoreMap":457},[462,2562,2563],{"class":464,"line":465},[462,2564,1325],{},[462,2566,2567],{"class":464,"line":471},[462,2568,2569],{},"    \u003Clistener-class>pl.xperios.rdk.server.startup.ServerStarter\u003C\u002Flistener-class>\n",[462,2571,2572],{"class":464,"line":478},[462,2573,1335],{},[426,2575,2576],{},"Poniżej znajduje się implementacja zamykania wszystkich połączeń dla C3p0, którą należy umieścić w listenerze Tomcata. Przykład:",[452,2578,2580],{"className":598,"code":2579,"language":600,"meta":457,"style":457},"public abstract class MainServerModuleManager implements EventListener {\n\n    @Override\n    public void contextInitialized(ServletContextEvent servletContextEvent) {\n        ...\n    }\n\n    @Override\n    public void contextDestroyed(ServletContextEvent servletContextEvent) {\n\n        try {\n            connection = dataSource.getConnection();\n        } catch (SQLException ex) {\n        } finally {\n            try {\n                if (connection != null) {\n                connection.close();\n            }\n\n            if (dataSource != null) {\n                try {\n                    DataSources.destroy(dataSource);\n                    dataSource = null;\n                } catch (Exception e) {\n                }\n            }\n            } catch (SQLException sQLException) {\n            }\n        }\n    }\n}\n",[459,2581,2582,2587,2591,2595,2599,2604,2608,2612,2616,2621,2625,2629,2634,2639,2644,2649,2654,2659,2663,2667,2672,2677,2682,2687,2692,2697,2701,2706,2710,2714,2718],{"__ignoreMap":457},[462,2583,2584],{"class":464,"line":465},[462,2585,2586],{},"public abstract class MainServerModuleManager implements EventListener {\n",[462,2588,2589],{"class":464,"line":471},[462,2590,475],{"emptyLinePlaceholder":474},[462,2592,2593],{"class":464,"line":478},[462,2594,1107],{},[462,2596,2597],{"class":464,"line":484},[462,2598,2256],{},[462,2600,2601],{"class":464,"line":489},[462,2602,2603],{},"        ...\n",[462,2605,2606],{"class":464,"line":495},[462,2607,702],{},[462,2609,2610],{"class":464,"line":501},[462,2611,475],{"emptyLinePlaceholder":474},[462,2613,2614],{"class":464,"line":506},[462,2615,1107],{},[462,2617,2618],{"class":464,"line":512},[462,2619,2620],{},"    public void contextDestroyed(ServletContextEvent servletContextEvent) {\n",[462,2622,2623],{"class":464,"line":518},[462,2624,475],{"emptyLinePlaceholder":474},[462,2626,2627],{"class":464,"line":524},[462,2628,1662],{},[462,2630,2631],{"class":464,"line":530},[462,2632,2633],{},"            connection = dataSource.getConnection();\n",[462,2635,2636],{"class":464,"line":536},[462,2637,2638],{},"        } catch (SQLException ex) {\n",[462,2640,2641],{"class":464,"line":542},[462,2642,2643],{},"        } finally {\n",[462,2645,2646],{"class":464,"line":547},[462,2647,2648],{},"            try {\n",[462,2650,2651],{"class":464,"line":553},[462,2652,2653],{},"                if (connection != null) {\n",[462,2655,2656],{"class":464,"line":558},[462,2657,2658],{},"                connection.close();\n",[462,2660,2661],{"class":464,"line":564},[462,2662,777],{},[462,2664,2665],{"class":464,"line":693},[462,2666,475],{"emptyLinePlaceholder":474},[462,2668,2669],{"class":464,"line":699},[462,2670,2671],{},"            if (dataSource != null) {\n",[462,2673,2674],{"class":464,"line":705},[462,2675,2676],{},"                try {\n",[462,2678,2679],{"class":464,"line":710},[462,2680,2681],{},"                    DataSources.destroy(dataSource);\n",[462,2683,2684],{"class":464,"line":715},[462,2685,2686],{},"                    dataSource = null;\n",[462,2688,2689],{"class":464,"line":721},[462,2690,2691],{},"                } catch (Exception e) {\n",[462,2693,2694],{"class":464,"line":727},[462,2695,2696],{},"                }\n",[462,2698,2699],{"class":464,"line":732},[462,2700,777],{},[462,2702,2703],{"class":464,"line":738},[462,2704,2705],{},"            } catch (SQLException sQLException) {\n",[462,2707,2708],{"class":464,"line":744},[462,2709,777],{},[462,2711,2712],{"class":464,"line":750},[462,2713,1077],{},[462,2715,2716],{"class":464,"line":756},[462,2717,702],{},[462,2719,2720],{"class":464,"line":762},[462,2721,811],{},[984,2723,986],{},{"title":457,"searchDepth":471,"depth":471,"links":2725},[],"2011-05-21","Naprawa zamykania puli (in Polish)",{"layout":993},"\u002Fblog\u002F2011-05-21-c3p0-proper-closing-application",{"title":2530,"description":2727},"2.blog\u002F2011-05-21-c3p0-proper-closing-application","KVhS-YS4azfp4TIUBSnuQqrywHNyd0do6ZmhiOAEn7c",{"id":2734,"title":2735,"authors":409,"badge":409,"body":2736,"date":3042,"description":3043,"extension":991,"image":409,"meta":3044,"navigation":474,"path":3045,"seo":3046,"stem":3047,"__hash__":3048},"posts\u002F2.blog\u002F2011-10-21-own-maven-repository-on-google-code.md","Prywatne repozytorium Maven na code.google.pl",{"type":423,"value":2737,"toc":3040},[2738,2753,2763,2766,2933,2936,2986,2989,3016,3019,3027,3030,3033,3038],[426,2739,2740,2741,2744,2745,2748,2749,2752],{},"Często tworząc nowy projekt (z reguły opensource) w naszym przypadku wykorzystujemy jako repozytorium popularny ",[459,2742,2743],{},"Github",", ",[459,2746,2747],{},"Bitbucket"," lub  ",[459,2750,2751],{},"code.google.com",". Aby podnieść walor biznesowy i jakość świadczonych usług normalnym jest częste wydawanie nowej wersji naszej aplikacji klientom \u002F społeczności. Proces ten czasmi jest dosyć tendencyjny i uciążliwy. Powtarzające się procesy oczywiście dociekliwy programista jest w stanie sobie zautomatyzować w bardzo zwinny sposób.",[426,2754,2755,2756,2758,2759,2762],{},"Dzisiaj pokażemy jak posiadając projekt na ",[459,2757,2751],{}," stworzyć z niego własne repozytorium wykorzystując do tego mavena w wersji ",[459,2760,2761],{},"3.0.3",".",[426,2764,2765],{},"plik pom.xml",[452,2767,2769],{"className":454,"code":2768,"language":456,"meta":457,"style":457},"\u003Cproject>\n\n    \u003Crepositories>\n        \u003Crepository>\n            \u003Cid>google\u003C\u002Fid>\n            \u003Cname>[Project Name] Maven Repository\u003C\u002Fname>\n            \u003Curl>https:\u002F\u002F[project-name].googlecode.com\u002Fsvn\u002Fmaven-repo\u002Freleases\u003C\u002Furl>\n        \u003C\u002Frepository>\n    \u003C\u002Frepositories>\n\n    \u003CdistributionManagement>\n        \u003Crepository>\n            \u003Cid>google\u003C\u002Fid>\n            \u003Cname>Maven Repository for Config Processor Plugin (releases)\u003C\u002Fname>\n            \u003Curl>dav:https:\u002F\u002F[project-name].googlecode.com\u002Fsvn\u002Fmaven-repo\u002Freleases\u003C\u002Furl>\n            \u003CuniqueVersion>false\u003C\u002FuniqueVersion>\n        \u003C\u002Frepository>\n        \u003CsnapshotRepository>\n            \u003Cid>google\u003C\u002Fid>\n            \u003Cname>Maven Repository for Config Processor Plugin (snapshots)\u003C\u002Fname>\n            \u003Curl>dav:https:\u002F\u002F[project-name].googlecode.com\u002Fsvn\u002Fmaven-repo\u002Fsnapshots\u003C\u002Furl>\n            \u003CuniqueVersion>false\u003C\u002FuniqueVersion>\n        \u003C\u002FsnapshotRepository>\n    \u003C\u002FdistributionManagement>\n\n    \u003Cbuild>\n        \u003Cextensions>\n            \u003Cextension>\n                \u003CgroupId>org.apache.maven.wagon\u003C\u002FgroupId>\n                \u003CartifactId>wagon-webdav\u003C\u002FartifactId>\n                \u003Cversion>1.0-beta-2\u003C\u002Fversion>\n            \u003C\u002Fextension>\n        \u003C\u002Fextensions>\n    \u003C\u002Fbuild>\n",[459,2770,2771,2776,2780,2785,2790,2795,2800,2805,2810,2815,2819,2824,2828,2832,2837,2842,2847,2851,2856,2860,2865,2870,2874,2879,2884,2888,2893,2898,2903,2908,2913,2918,2923,2928],{"__ignoreMap":457},[462,2772,2773],{"class":464,"line":465},[462,2774,2775],{},"\u003Cproject>\n",[462,2777,2778],{"class":464,"line":471},[462,2779,475],{"emptyLinePlaceholder":474},[462,2781,2782],{"class":464,"line":478},[462,2783,2784],{},"    \u003Crepositories>\n",[462,2786,2787],{"class":464,"line":484},[462,2788,2789],{},"        \u003Crepository>\n",[462,2791,2792],{"class":464,"line":489},[462,2793,2794],{},"            \u003Cid>google\u003C\u002Fid>\n",[462,2796,2797],{"class":464,"line":495},[462,2798,2799],{},"            \u003Cname>[Project Name] Maven Repository\u003C\u002Fname>\n",[462,2801,2802],{"class":464,"line":501},[462,2803,2804],{},"            \u003Curl>https:\u002F\u002F[project-name].googlecode.com\u002Fsvn\u002Fmaven-repo\u002Freleases\u003C\u002Furl>\n",[462,2806,2807],{"class":464,"line":506},[462,2808,2809],{},"        \u003C\u002Frepository>\n",[462,2811,2812],{"class":464,"line":512},[462,2813,2814],{},"    \u003C\u002Frepositories>\n",[462,2816,2817],{"class":464,"line":518},[462,2818,475],{"emptyLinePlaceholder":474},[462,2820,2821],{"class":464,"line":524},[462,2822,2823],{},"    \u003CdistributionManagement>\n",[462,2825,2826],{"class":464,"line":530},[462,2827,2789],{},[462,2829,2830],{"class":464,"line":536},[462,2831,2794],{},[462,2833,2834],{"class":464,"line":542},[462,2835,2836],{},"            \u003Cname>Maven Repository for Config Processor Plugin (releases)\u003C\u002Fname>\n",[462,2838,2839],{"class":464,"line":547},[462,2840,2841],{},"            \u003Curl>dav:https:\u002F\u002F[project-name].googlecode.com\u002Fsvn\u002Fmaven-repo\u002Freleases\u003C\u002Furl>\n",[462,2843,2844],{"class":464,"line":553},[462,2845,2846],{},"            \u003CuniqueVersion>false\u003C\u002FuniqueVersion>\n",[462,2848,2849],{"class":464,"line":558},[462,2850,2809],{},[462,2852,2853],{"class":464,"line":564},[462,2854,2855],{},"        \u003CsnapshotRepository>\n",[462,2857,2858],{"class":464,"line":693},[462,2859,2794],{},[462,2861,2862],{"class":464,"line":699},[462,2863,2864],{},"            \u003Cname>Maven Repository for Config Processor Plugin (snapshots)\u003C\u002Fname>\n",[462,2866,2867],{"class":464,"line":705},[462,2868,2869],{},"            \u003Curl>dav:https:\u002F\u002F[project-name].googlecode.com\u002Fsvn\u002Fmaven-repo\u002Fsnapshots\u003C\u002Furl>\n",[462,2871,2872],{"class":464,"line":710},[462,2873,2846],{},[462,2875,2876],{"class":464,"line":715},[462,2877,2878],{},"        \u003C\u002FsnapshotRepository>\n",[462,2880,2881],{"class":464,"line":721},[462,2882,2883],{},"    \u003C\u002FdistributionManagement>\n",[462,2885,2886],{"class":464,"line":727},[462,2887,475],{"emptyLinePlaceholder":474},[462,2889,2890],{"class":464,"line":732},[462,2891,2892],{},"    \u003Cbuild>\n",[462,2894,2895],{"class":464,"line":738},[462,2896,2897],{},"        \u003Cextensions>\n",[462,2899,2900],{"class":464,"line":744},[462,2901,2902],{},"            \u003Cextension>\n",[462,2904,2905],{"class":464,"line":750},[462,2906,2907],{},"                \u003CgroupId>org.apache.maven.wagon\u003C\u002FgroupId>\n",[462,2909,2910],{"class":464,"line":756},[462,2911,2912],{},"                \u003CartifactId>wagon-webdav\u003C\u002FartifactId>\n",[462,2914,2915],{"class":464,"line":762},[462,2916,2917],{},"                \u003Cversion>1.0-beta-2\u003C\u002Fversion>\n",[462,2919,2920],{"class":464,"line":768},[462,2921,2922],{},"            \u003C\u002Fextension>\n",[462,2924,2925],{"class":464,"line":774},[462,2926,2927],{},"        \u003C\u002Fextensions>\n",[462,2929,2930],{"class":464,"line":780},[462,2931,2932],{},"    \u003C\u002Fbuild>\n",[426,2934,2935],{},"i dodatkowo w pliku settings.xml:",[452,2937,2939],{"className":454,"code":2938,"language":456,"meta":457,"style":457},"\u003Cservers>\n    \u003Cserver>\n        \u003Cid>google\u003C\u002Fid>\n        \u003Cusername>[my-login]\u003C\u002Fusername>\n        \u003Cpassword>[my password]\u003C\u002Fpassword>\n        \u003CfilePermissions>775\u003C\u002FfilePermissions>\n        \u003CdirectoryPermissions>775\u003C\u002FdirectoryPermissions>\n    \u003C\u002Fserver>\n\u003C\u002Fservers>\n",[459,2940,2941,2946,2951,2956,2961,2966,2971,2976,2981],{"__ignoreMap":457},[462,2942,2943],{"class":464,"line":465},[462,2944,2945],{},"\u003Cservers>\n",[462,2947,2948],{"class":464,"line":471},[462,2949,2950],{},"    \u003Cserver>\n",[462,2952,2953],{"class":464,"line":478},[462,2954,2955],{},"        \u003Cid>google\u003C\u002Fid>\n",[462,2957,2958],{"class":464,"line":484},[462,2959,2960],{},"        \u003Cusername>[my-login]\u003C\u002Fusername>\n",[462,2962,2963],{"class":464,"line":489},[462,2964,2965],{},"        \u003Cpassword>[my password]\u003C\u002Fpassword>\n",[462,2967,2968],{"class":464,"line":495},[462,2969,2970],{},"        \u003CfilePermissions>775\u003C\u002FfilePermissions>\n",[462,2972,2973],{"class":464,"line":501},[462,2974,2975],{},"        \u003CdirectoryPermissions>775\u003C\u002FdirectoryPermissions>\n",[462,2977,2978],{"class":464,"line":506},[462,2979,2980],{},"    \u003C\u002Fserver>\n",[462,2982,2983],{"class":464,"line":512},[462,2984,2985],{},"\u003C\u002Fservers>\n",[426,2987,2988],{},"Objaśnienia poszczególnych elementów w pliku pom.xml:",[439,2990,2991,3001,3010],{},[442,2992,2993,2997,2998],{},[2994,2995,2996],"strong",{},"repositories -> repository"," – wskazuje miejsce wyszukiwania artefaktów umieszczonych z innych projektów\ndistributionManagement -> repository – wskazuje miejsce, gdzie nowo skompilowane wersje zostaną uploadowane w fazie deploy; w tym miejscu pojawią się jedynie wersje, które nie są opatrzone suffixem SNAPSHOT w wersji projektu np: ",[459,2999,3000],{},"\u003Cversion>1.0.1\u003C\u002Fversion>",[442,3002,3003,3006,3007],{},[2994,3004,3005],{},"distributionManagement -> snapshotRepository"," – wskazuje miejsce, gdzie nowo skompilowane wersje zostaną uploadowane w fazie deploy; w tym miejscu pojawią się jedynie wersje, które są opatrzone suffixem SNAPSHOT w wersji projektu np: ",[459,3008,3009],{},"\u003Cversion>1.0.1-SNAPSHOT\u003C\u002Fversion>",[442,3011,3012,3015],{},[2994,3013,3014],{},"extension"," - dodany connector, który obsługuje protokół webDav, który jest implementowany przez subversion wykorzystywany przez code.google.com",[426,3017,3018],{},"Objaśnienia poszczególnych elementów w pliku settings.xml:",[439,3020,3021],{},[442,3022,3023,3026],{},[2994,3024,3025],{},"servers -> server"," – definiuje loginy i hasła do konta dostępowego z prawami zapisu do projektu",[426,3028,3029],{},"Jeżeli występuje błąd 401 oznacza to błąd autoryzacji dla powyższych danych.",[426,3031,3032],{},"Projekt zostanie uploadowany na serwer w fazie deploy dlatego aby przetestować nową funkcjonalność wydajemy polecenie:",[426,3034,3035],{},[459,3036,3037],{},"mvn clean install deploy:deploy",[984,3039,986],{},{"title":457,"searchDepth":471,"depth":471,"links":3041},[],"2011-10-21","Tworzenie i konfiguracja prywatnego repozytorium Maven (in Polish)",{"layout":993},"\u002Fblog\u002F2011-10-21-own-maven-repository-on-google-code",{"title":2735,"description":3043},"2.blog\u002F2011-10-21-own-maven-repository-on-google-code","vgIdG8KvCReZWzmNsHwYoiDbWAEJEsY179OX6YW7Grg",{"id":3050,"title":3051,"authors":409,"badge":409,"body":3052,"date":3448,"description":3449,"extension":991,"image":409,"meta":3450,"navigation":474,"path":3451,"seo":3452,"stem":3453,"__hash__":3454},"posts\u002F2.blog\u002F2011-10-22-maven-site.md","Maven site",{"type":423,"value":3053,"toc":3446},[3054,3057,3074,3077,3080,3083,3096,3250,3257,3265,3271,3278,3286,3289,3315,3342,3345,3380,3383,3426,3429,3438,3444],[426,3055,3056],{},"Jak wiadomo kolejnym etapem po, a jeszcze lepiej w trakcie realizacji projektu należy przedstawić klientowi dokumentację zarówno użytkownika jak i techniczną. Abstrahując zupełnie od dokumentacji użytkownika dokumentacja techniczna powinna zawierać przynajmniej takie podstawowe elementy jak:",[439,3058,3059,3062,3065,3068,3071],{},[442,3060,3061],{},"javadoc,",[442,3063,3064],{},"FAQ,",[442,3066,3067],{},"opis użycia,",[442,3069,3070],{},"pokrycie kotu testami,",[442,3072,3073],{},"wyniki testów,",[426,3075,3076],{},"i wiele innych zależących od wymogów klientów, góry czy własnych wymagań.",[426,3078,3079],{},"Oprócz części opisowej, którą prowadzić programista musi samodzielnie, w większości powyższych przypadków może wyręczyć nas maven. Dokumentacja generowana jest do postaci strony HTML, którą później można udostępnić w internecie bądź intranecie podobnie jak robi to dosyć spora rzesza producentów oprogramowania w tym sam twórca mavena – apache.",[426,3081,3082],{},"Struktura strony",[426,3084,3085,3086,3089,3090,3095],{},"Definicja struktury strony musi znajdować się w pliku: ",[459,3087,3088],{},"\\src\\site\\site.xml"," i powinna mieć strukturę zgonie z ",[977,3091,3094],{"href":3092,"rel":3093},"http:\u002F\u002Fmaven.apache.org\u002Fguides\u002Fmini\u002Fguide-site.html",[981],"dokumentacją",":",[452,3097,3099],{"className":454,"code":3098,"language":456,"meta":457,"style":457},"\u003C?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n\u003Cproject name=\"Maven\">\n\n    \u003CbannerLeft>\n        \u003Cname>Maven\u003C\u002Fname>\n        \u003Csrc>http:\u002F\u002Fmaven.apache.org\u002Fimages\u002Fapache-maven-project.png\u003C\u002Fsrc>\n        \u003Chref>http:\u002F\u002Fmaven.apache.org\u002F\u003C\u002Fhref>\n    \u003C\u002FbannerLeft>\n    \u003CbannerRight>\n        \u003Csrc>http:\u002F\u002Fmaven.apache.org\u002Fimages\u002Fmaven-small.gif\u003C\u002Fsrc>\n    \u003C\u002FbannerRight>\n    \u003Cbody>\n        \u003Clinks>\n            \u003Citem name=\"Project Name\" href=\"http:\u002F\u002Fwww.project_name.company_name.com\u002F\" \u002F>\n        \u003C\u002Flinks>\n\n        \u003Cmenu name=\"Maven 2.0\">\n            \u003Citem name=\"Introduction\" href=\"index.html\"\u002F>\n            \u003Citem name=\"Download\" href=\"download.html\"\u002F>\n            \u003Citem name=\"Release Notes\" href=\"release-notes.html\" \u002F>\n            \u003Citem name=\"General Information\" href=\"about.html\"\u002F>\n            \u003Citem name=\"For Maven 1.x Users\" href=\"maven1.html\"\u002F>\n            \u003Citem name=\"Road Map\" href=\"roadmap.html\" \u002F>\n            \u003Citem name=\"FAQ\" href=\"faq.html\" \u002F>\n        \u003C\u002Fmenu>\n\n        \u003Cmenu ref=\"modules\" \u002F>\n        \u003Cmenu ref=\"reports\"\u002F>\n\n    \u003C\u002Fbody>\n\u003C\u002Fproject>\n",[459,3100,3101,3106,3111,3115,3120,3125,3130,3135,3140,3145,3150,3155,3159,3164,3169,3174,3178,3183,3188,3193,3198,3203,3208,3213,3218,3223,3227,3232,3237,3241,3245],{"__ignoreMap":457},[462,3102,3103],{"class":464,"line":465},[462,3104,3105],{},"\u003C?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n",[462,3107,3108],{"class":464,"line":471},[462,3109,3110],{},"\u003Cproject name=\"Maven\">\n",[462,3112,3113],{"class":464,"line":478},[462,3114,475],{"emptyLinePlaceholder":474},[462,3116,3117],{"class":464,"line":484},[462,3118,3119],{},"    \u003CbannerLeft>\n",[462,3121,3122],{"class":464,"line":489},[462,3123,3124],{},"        \u003Cname>Maven\u003C\u002Fname>\n",[462,3126,3127],{"class":464,"line":495},[462,3128,3129],{},"        \u003Csrc>http:\u002F\u002Fmaven.apache.org\u002Fimages\u002Fapache-maven-project.png\u003C\u002Fsrc>\n",[462,3131,3132],{"class":464,"line":501},[462,3133,3134],{},"        \u003Chref>http:\u002F\u002Fmaven.apache.org\u002F\u003C\u002Fhref>\n",[462,3136,3137],{"class":464,"line":506},[462,3138,3139],{},"    \u003C\u002FbannerLeft>\n",[462,3141,3142],{"class":464,"line":512},[462,3143,3144],{},"    \u003CbannerRight>\n",[462,3146,3147],{"class":464,"line":518},[462,3148,3149],{},"        \u003Csrc>http:\u002F\u002Fmaven.apache.org\u002Fimages\u002Fmaven-small.gif\u003C\u002Fsrc>\n",[462,3151,3152],{"class":464,"line":524},[462,3153,3154],{},"    \u003C\u002FbannerRight>\n",[462,3156,3157],{"class":464,"line":530},[462,3158,879],{},[462,3160,3161],{"class":464,"line":536},[462,3162,3163],{},"        \u003Clinks>\n",[462,3165,3166],{"class":464,"line":542},[462,3167,3168],{},"            \u003Citem name=\"Project Name\" href=\"http:\u002F\u002Fwww.project_name.company_name.com\u002F\" \u002F>\n",[462,3170,3171],{"class":464,"line":547},[462,3172,3173],{},"        \u003C\u002Flinks>\n",[462,3175,3176],{"class":464,"line":553},[462,3177,475],{"emptyLinePlaceholder":474},[462,3179,3180],{"class":464,"line":558},[462,3181,3182],{},"        \u003Cmenu name=\"Maven 2.0\">\n",[462,3184,3185],{"class":464,"line":564},[462,3186,3187],{},"            \u003Citem name=\"Introduction\" href=\"index.html\"\u002F>\n",[462,3189,3190],{"class":464,"line":693},[462,3191,3192],{},"            \u003Citem name=\"Download\" href=\"download.html\"\u002F>\n",[462,3194,3195],{"class":464,"line":699},[462,3196,3197],{},"            \u003Citem name=\"Release Notes\" href=\"release-notes.html\" \u002F>\n",[462,3199,3200],{"class":464,"line":705},[462,3201,3202],{},"            \u003Citem name=\"General Information\" href=\"about.html\"\u002F>\n",[462,3204,3205],{"class":464,"line":710},[462,3206,3207],{},"            \u003Citem name=\"For Maven 1.x Users\" href=\"maven1.html\"\u002F>\n",[462,3209,3210],{"class":464,"line":715},[462,3211,3212],{},"            \u003Citem name=\"Road Map\" href=\"roadmap.html\" \u002F>\n",[462,3214,3215],{"class":464,"line":721},[462,3216,3217],{},"            \u003Citem name=\"FAQ\" href=\"faq.html\" \u002F>\n",[462,3219,3220],{"class":464,"line":727},[462,3221,3222],{},"        \u003C\u002Fmenu>\n",[462,3224,3225],{"class":464,"line":732},[462,3226,475],{"emptyLinePlaceholder":474},[462,3228,3229],{"class":464,"line":738},[462,3230,3231],{},"        \u003Cmenu ref=\"modules\" \u002F>\n",[462,3233,3234],{"class":464,"line":744},[462,3235,3236],{},"        \u003Cmenu ref=\"reports\"\u002F>\n",[462,3238,3239],{"class":464,"line":750},[462,3240,475],{"emptyLinePlaceholder":474},[462,3242,3243],{"class":464,"line":756},[462,3244,889],{},[462,3246,3247],{"class":464,"line":762},[462,3248,3249],{},"\u003C\u002Fproject>\n",[426,3251,3252,3253,3256],{},"Niestety od czasu mavena 2 wprowadzono reorganizację struktury projektu co zaowocowało zmianą filozofii wykorzystywania niektórych modułów w tym generowania site-ów. Tym sposobem dokumentacja przeznaczona dla wcześniejszych wersji, której jest ogromna ilość w internecie może powodować zamęt i błędy podczas próby generowania strony. W wersji ",[459,3254,3255],{},"3.0.x"," należy dodać następujący plugin w pliku pom.xml:",[452,3258,3263],{"className":3259,"code":3261,"language":3262},[3260],"language-text","\u003Cplugins>\n    \u003Cplugin>\n        \u003CgroupId>org.apache.maven.plugins\u003C\u002FgroupId>\n        \u003CartifactId>maven-site-plugin\u003C\u002FartifactId>\n        \u003Cversion>3.0-beta-2\u003C\u002Fversion>\n    \u003C\u002Fplugin>\n\u003C\u002Fplugins>\n","text",[459,3264,3261],{"__ignoreMap":457},[426,3266,3267,3268],{},"Aby przetestować działanie pluginu należy wydać polecenie: ",[459,3269,3270],{},"clean:clean site:site",[426,3272,3273,3274,3277],{},"Po uruchomieniu strony znajdującej się w ",[459,3275,3276],{},"target\\site\\index.html"," naszym oczom ukaże się strona jak na załączonym zrzucie:",[426,3279,3280],{},[977,3281,3283],{"href":3282},"\u002Fposts\u002Fassets\u002Fsite_page.jpg",[3284,3285],"img",{"src":3282},[426,3287,3288],{},"Strona HTML czyli site może zostać wygenerowany domyślnie z kilku typów źródeł danych takich jak:",[439,3290,3291,3299,3307],{},[442,3292,3293,3298],{},[977,3294,3297],{"href":3295,"rel":3296},"http:\u002F\u002Fmaven.apache.org\u002Fdoxia\u002Freferences\u002Fapt-format.html",[981],"apt"," - Almost Plain Text (strony statyczne)",[442,3300,3301,3306],{},[977,3302,3305],{"href":3303,"rel":3304},"http:\u002F\u002Fmaven.apache.org\u002Fdoxia\u002Freferences\u002Fxdoc-format.html",[981],"xdoc"," (strony statyczne)",[442,3308,3309,3314],{},[977,3310,3313],{"href":3311,"rel":3312},"http:\u002F\u002Fmaven.apache.org\u002Fdoxia\u002Freferences\u002Ffml-format.html",[981],"fml"," - FAQ",[426,3316,3317,3318,3323,3324,3329,3330,3335,3336,3341],{},"oraz poprzez dostarczenie dodatkowych treści poprzez ",[977,3319,3322],{"href":3320,"rel":3321},"http:\u002F\u002Fmaven.apache.org\u002Fplugins\u002Fmaven-site-plugin\u002Fmaven-3.html",[981],"pluginy",". Stronę taką można ",[977,3325,3328],{"href":3326,"rel":3327},"http:\u002F\u002Fmaven.apache.org\u002Fplugins\u002Fmaven-site-plugin\u002Fi18n.html",[981],"internacjonalizować"," oraz zmieniać jej wygląd poprzez ",[977,3331,3334],{"href":3332,"rel":3333},"http:\u002F\u002Fmaven.apache.org\u002Fplugins\u002Fmaven-site-plugin\u002Fexamples\u002Ftemplatefile.html",[981],"skórki",". Więcej informacji na temat pluginu oraz jego możliwości dostępnych jest na ",[977,3337,3340],{"href":3338,"rel":3339},"http:\u002F\u002Fmaven.apache.org\u002Fplugins\u002Fmaven-site-plugin\u002Findex.html",[981],"oficjalnej stronie"," wygenerowanej również przy pomocy mavena.",[426,3343,3344],{},"Ostatnią rzeczą jaką będziemy chcieli zrobić to umieszczenie naszego site-a na serwerze, do którego będą mieli dostęp użytkownicy naszego projektu. W tym celu musimy do naszego pliku pom.xml dodać wpis gdzie chcemy ją umieścić:",[452,3346,3348],{"className":454,"code":3347,"language":456,"meta":457,"style":457},"\u003CdistributionManagement>\n    \u003Csite>\n        \u003Cid>mycompany\u003C\u002Fid>\n        \u003Curl>ftp:\u002F\u002Fmycompany.com\u002Fpublic_html\u002Fsite\u002Fmy_product_site\u003C\u002Furl>\n    \u003C\u002Fsite>\n\u003C\u002FdistributionManagement>\n",[459,3349,3350,3355,3360,3365,3370,3375],{"__ignoreMap":457},[462,3351,3352],{"class":464,"line":465},[462,3353,3354],{},"\u003CdistributionManagement>\n",[462,3356,3357],{"class":464,"line":471},[462,3358,3359],{},"    \u003Csite>\n",[462,3361,3362],{"class":464,"line":478},[462,3363,3364],{},"        \u003Cid>mycompany\u003C\u002Fid>\n",[462,3366,3367],{"class":464,"line":484},[462,3368,3369],{},"        \u003Curl>ftp:\u002F\u002Fmycompany.com\u002Fpublic_html\u002Fsite\u002Fmy_product_site\u003C\u002Furl>\n",[462,3371,3372],{"class":464,"line":489},[462,3373,3374],{},"    \u003C\u002Fsite>\n",[462,3376,3377],{"class":464,"line":495},[462,3378,3379],{},"\u003C\u002FdistributionManagement>\n",[426,3381,3382],{},"oraz należy stworzyć plik settings.xml obok pom.xml, w którym podamy dane niezbędne do logowania się przez protokół ftp:",[452,3384,3386],{"className":454,"code":3385,"language":456,"meta":457,"style":457},"\u003Cservers>\n    \u003Cserver>\n        \u003Cid>mycompany\u003C\u002Fid>\n        \u003Cusername>username\u003C\u002Fusername>\n        \u003Cpassword>password\u003C\u002Fpassword>\n        \u003CfilePermissions>775\u003C\u002FfilePermissions>\n        \u003CdirectoryPermissions>775\u003C\u002FdirectoryPermissions>\n    \u003C\u002Fserver>\n\u003C\u002Fservers>\n",[459,3387,3388,3392,3396,3400,3405,3410,3414,3418,3422],{"__ignoreMap":457},[462,3389,3390],{"class":464,"line":465},[462,3391,2945],{},[462,3393,3394],{"class":464,"line":471},[462,3395,2950],{},[462,3397,3398],{"class":464,"line":478},[462,3399,3364],{},[462,3401,3402],{"class":464,"line":484},[462,3403,3404],{},"        \u003Cusername>username\u003C\u002Fusername>\n",[462,3406,3407],{"class":464,"line":489},[462,3408,3409],{},"        \u003Cpassword>password\u003C\u002Fpassword>\n",[462,3411,3412],{"class":464,"line":495},[462,3413,2970],{},[462,3415,3416],{"class":464,"line":501},[462,3417,2975],{},[462,3419,3420],{"class":464,"line":506},[462,3421,2980],{},[462,3423,3424],{"class":464,"line":512},[462,3425,2985],{},[426,3427,3428],{},"Hasło niestety należy podać w postaci jawnej, dlatego nie należy pliku settings.xml wysyłać do repozytorium. Każdy użytkownik, który jest odpowiedzialny za publikację site-a powinien mieć zdefiniowany własny login i hasło poza udostępnionymi elementami.",[426,3430,3431,3432,3437],{},"Oczywiście nie jest to wciąż najbezpieczniejsza metoda przechowywania hasła przed nieporządanym dostępem dlatego można hasła szyfrować za pomocą ",[977,3433,3436],{"href":3434,"rel":3435},"http:\u002F\u002Fmaven.apache.org\u002Fguides\u002Fmini\u002Fguide-encryption.html#How_to_encrypt_server_passwords",[981],"tej"," metody.",[426,3439,3440,3441],{},"Aby umieścić stronę na zdalnym serwerze należy wydać polecenie: ",[459,3442,3443],{},"site:deploy",[984,3445,986],{},{"title":457,"searchDepth":471,"depth":471,"links":3447},[],"2011-10-22","Tworzenie dokumentacji projektu przy pomocy mechanizmu site z Mavena (in Polish)",{"layout":993},"\u002Fblog\u002F2011-10-22-maven-site",{"title":3051,"description":3449},"2.blog\u002F2011-10-22-maven-site","wA1wP86CCfIecsbCtbogZmMk7-S6Bfo_aUnPDiGIm00",{"id":3456,"title":3457,"authors":409,"badge":409,"body":3458,"date":3758,"description":3759,"extension":991,"image":409,"meta":3760,"navigation":474,"path":3761,"seo":3762,"stem":3763,"__hash__":3764},"posts\u002F2.blog\u002F2011-10-23-releasing-archived-maven-archetypes.md","Wydawanie aplikacji w formie zarchiwizowanej",{"type":423,"value":3459,"toc":3756},[3460,3463,3471,3474,3477,3527,3534,3541,3716,3724,3727,3750,3753],[426,3461,3462],{},"Jednym z elementów cyklu życia projektu jest wydanie jego wersji. W zależności co tak na prawdę tworzymy efektem końcowym jest aplikacja gotowa do uruchomienia przez klienta, bądź biblioteka wykorzystywana w innych projektach. Oto czym się głównie charakteryzują:",[439,3464,3465,3468],{},[442,3466,3467],{},"aplikacja – posiada strukturę dostosowaną do projektu (jednakowa nazwa artefaktu np.: aplikacja.jar, zależności umieszczone w folderze lib, zasoby porozmieszczane w oddzielnych folderach np.: Pomoc, Img, Log, Raporty itp.), dokumentacja użytkownika, przykładowe pliki konfiguracyjne, dołączone jedynie binaria",[442,3469,3470],{},"biblioteka – ustandaryzowana struktura wydania (dobra konwencja), dołączenie binariów, bardzo często nie dołącza się zależności, przykłady, dokumentacja techniczna, strona site-ów wraz z wynikami testów, javadoc itp.",[426,3472,3473],{},"Oczywiście powyższy opis może odbiegać nawet znacząco od realiów panujących w waszej firmie, niemniej chodzi o to, że istnieją znaczące różnice w sposobach wydawania wersji.",[426,3475,3476],{},"W dniu dzisiejszym zajmiemy się tworzeniem archiwum zip, które będzie zawierało gotową do publikacji aplikację \u002F bibliotekę. Do tego celu posłuży nam Maven w wersji 3.0.3. Już samo stosowanie Mavena wymusza w naszym projekcie usystematyzowaną strukturę. Dzięki temu łatwiej możemy otrzymać formę wynikową opracowaną i akceptowaną przez ogromne rzesze użytkowników.\nPierwszym elementem jaki należy dodać odpowiedni plugin assembly:",[452,3478,3480],{"className":454,"code":3479,"language":456,"meta":457,"style":457},"\u003Cplugin>\n    \u003CartifactId>maven-assembly-plugin\u003C\u002FartifactId>\n        \u003Cconfiguration>\n            \u003Cdescriptors>\n                \u003Cdescriptor>src\u002Fmain\u002Fassembly\u002Fbin.xml\u003C\u002Fdescriptor>\n            \u003C\u002Fdescriptors>\n        \u003CfinalName>${artifactId}\u003C\u002FfinalName>\n    \u003C\u002Fconfiguration>\n\u003C\u002Fplugin>\n",[459,3481,3482,3487,3492,3497,3502,3507,3512,3517,3522],{"__ignoreMap":457},[462,3483,3484],{"class":464,"line":465},[462,3485,3486],{},"\u003Cplugin>\n",[462,3488,3489],{"class":464,"line":471},[462,3490,3491],{},"    \u003CartifactId>maven-assembly-plugin\u003C\u002FartifactId>\n",[462,3493,3494],{"class":464,"line":478},[462,3495,3496],{},"        \u003Cconfiguration>\n",[462,3498,3499],{"class":464,"line":484},[462,3500,3501],{},"            \u003Cdescriptors>\n",[462,3503,3504],{"class":464,"line":489},[462,3505,3506],{},"                \u003Cdescriptor>src\u002Fmain\u002Fassembly\u002Fbin.xml\u003C\u002Fdescriptor>\n",[462,3508,3509],{"class":464,"line":495},[462,3510,3511],{},"            \u003C\u002Fdescriptors>\n",[462,3513,3514],{"class":464,"line":501},[462,3515,3516],{},"        \u003CfinalName>${artifactId}\u003C\u002FfinalName>\n",[462,3518,3519],{"class":464,"line":506},[462,3520,3521],{},"    \u003C\u002Fconfiguration>\n",[462,3523,3524],{"class":464,"line":512},[462,3525,3526],{},"\u003C\u002Fplugin>\n",[426,3528,3529,3530,3533],{},"Definiujemy w nim ścieżkę deskryptora, czyli pliku w którym określimy co zostanie dołączone do archiwum. Gol ",[459,3531,3532],{},"assembly:assembly"," uruchamiający pakowanie powinien zostać wywołany po fazie build dzięki czemu w folderze target będziemy mieli już stworzoną pełną strukturę z której będziemy dysponowali skompilowanymi plikami, które możemy dołączać do archiwum.",[426,3535,3536,3537,3540],{},"Oczywiście następnym krokiem będzie stworzenie pliku ",[459,3538,3539],{},"src\u002Fmain\u002Fassembly\u002Fbin.xml",", który w naszym przypadku może wyglądać następująco:",[452,3542,3544],{"className":454,"code":3543,"language":456,"meta":457,"style":457},"\u003C?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\u003Cassembly xmlns=\"http:\u002F\u002Fmaven.apache.org\u002Fplugins\u002Fmaven-assembly-plugin\u002Fassembly\u002F1.1.2\" xmlns:xsi=\"http:\u002F\u002Fwww.w3.org\u002F2001\u002FXMLSchema-instance\"\n    xsi:schemaLocation=\"http:\u002F\u002Fmaven.apache.org\u002Fplugins\u002Fmaven-assembly-plugin\u002Fassembly\u002F1.1.2 http:\u002F\u002Fmaven.apache.org\u002Fxsd\u002Fassembly-1.1.2.xsd\">>\n    \u003Cid>bin\u003C\u002Fid>\n    \u003Cformats>\n        \u003Cformat>zip\u003C\u002Fformat>\n    \u003C\u002Fformats>\n    \u003CincludeSiteDirectory>true\u003C\u002FincludeSiteDirectory>\n    \u003CfileSets>\n        \u003CfileSet>\n            \u003Cincludes>\n                \u003Cinclude>Config.properties\u003C\u002Finclude>\n            \u003Cinclude>start.bat\u003C\u002Finclude>\n        \u003C\u002Fincludes>\n        \u003C\u002FfileSet>\n        \u003CfileSet>\n        \u003Cdirectory>target\u003C\u002Fdirectory>\n        \u003CoutputDirectory>.\u003C\u002FoutputDirectory>\n        \u003Cincludes>\n            \u003Cinclude>${artifactId}.jar\u003C\u002Finclude>\n        \u003C\u002Fincludes>\n        \u003C\u002FfileSet>\n        \u003CfileSet>\n            \u003Cdirectory>target\u002FPomoc\u003C\u002Fdirectory>\n            \u003CoutputDirectory>Pomoc\u003C\u002FoutputDirectory>\n        \u003C\u002FfileSet>\n        \u003CfileSet>\n            \u003Cdirectory>target\u002FFonts\u003C\u002Fdirectory>\n            \u003CoutputDirectory>Fonts\u003C\u002FoutputDirectory>\n        \u003C\u002FfileSet>\n        \u003CfileSet>\n            \u003Cdirectory>target\u002Flib\u003C\u002Fdirectory>\n            \u003CoutputDirectory>lib\u003C\u002FoutputDirectory>\n        \u003C\u002FfileSet>\n    \u003C\u002FfileSets>\n\u003C\u002Fassembly>\n",[459,3545,3546,3550,3555,3560,3565,3570,3575,3580,3585,3590,3595,3600,3605,3610,3615,3620,3624,3629,3634,3639,3644,3648,3652,3656,3661,3666,3670,3674,3679,3684,3688,3692,3697,3702,3706,3711],{"__ignoreMap":457},[462,3547,3548],{"class":464,"line":465},[462,3549,468],{},[462,3551,3552],{"class":464,"line":471},[462,3553,3554],{},"\u003Cassembly xmlns=\"http:\u002F\u002Fmaven.apache.org\u002Fplugins\u002Fmaven-assembly-plugin\u002Fassembly\u002F1.1.2\" xmlns:xsi=\"http:\u002F\u002Fwww.w3.org\u002F2001\u002FXMLSchema-instance\"\n",[462,3556,3557],{"class":464,"line":478},[462,3558,3559],{},"    xsi:schemaLocation=\"http:\u002F\u002Fmaven.apache.org\u002Fplugins\u002Fmaven-assembly-plugin\u002Fassembly\u002F1.1.2 http:\u002F\u002Fmaven.apache.org\u002Fxsd\u002Fassembly-1.1.2.xsd\">>\n",[462,3561,3562],{"class":464,"line":484},[462,3563,3564],{},"    \u003Cid>bin\u003C\u002Fid>\n",[462,3566,3567],{"class":464,"line":489},[462,3568,3569],{},"    \u003Cformats>\n",[462,3571,3572],{"class":464,"line":495},[462,3573,3574],{},"        \u003Cformat>zip\u003C\u002Fformat>\n",[462,3576,3577],{"class":464,"line":501},[462,3578,3579],{},"    \u003C\u002Fformats>\n",[462,3581,3582],{"class":464,"line":506},[462,3583,3584],{},"    \u003CincludeSiteDirectory>true\u003C\u002FincludeSiteDirectory>\n",[462,3586,3587],{"class":464,"line":512},[462,3588,3589],{},"    \u003CfileSets>\n",[462,3591,3592],{"class":464,"line":518},[462,3593,3594],{},"        \u003CfileSet>\n",[462,3596,3597],{"class":464,"line":524},[462,3598,3599],{},"            \u003Cincludes>\n",[462,3601,3602],{"class":464,"line":530},[462,3603,3604],{},"                \u003Cinclude>Config.properties\u003C\u002Finclude>\n",[462,3606,3607],{"class":464,"line":536},[462,3608,3609],{},"            \u003Cinclude>start.bat\u003C\u002Finclude>\n",[462,3611,3612],{"class":464,"line":542},[462,3613,3614],{},"        \u003C\u002Fincludes>\n",[462,3616,3617],{"class":464,"line":547},[462,3618,3619],{},"        \u003C\u002FfileSet>\n",[462,3621,3622],{"class":464,"line":553},[462,3623,3594],{},[462,3625,3626],{"class":464,"line":558},[462,3627,3628],{},"        \u003Cdirectory>target\u003C\u002Fdirectory>\n",[462,3630,3631],{"class":464,"line":564},[462,3632,3633],{},"        \u003CoutputDirectory>.\u003C\u002FoutputDirectory>\n",[462,3635,3636],{"class":464,"line":693},[462,3637,3638],{},"        \u003Cincludes>\n",[462,3640,3641],{"class":464,"line":699},[462,3642,3643],{},"            \u003Cinclude>${artifactId}.jar\u003C\u002Finclude>\n",[462,3645,3646],{"class":464,"line":705},[462,3647,3614],{},[462,3649,3650],{"class":464,"line":710},[462,3651,3619],{},[462,3653,3654],{"class":464,"line":715},[462,3655,3594],{},[462,3657,3658],{"class":464,"line":721},[462,3659,3660],{},"            \u003Cdirectory>target\u002FPomoc\u003C\u002Fdirectory>\n",[462,3662,3663],{"class":464,"line":727},[462,3664,3665],{},"            \u003CoutputDirectory>Pomoc\u003C\u002FoutputDirectory>\n",[462,3667,3668],{"class":464,"line":732},[462,3669,3619],{},[462,3671,3672],{"class":464,"line":738},[462,3673,3594],{},[462,3675,3676],{"class":464,"line":744},[462,3677,3678],{},"            \u003Cdirectory>target\u002FFonts\u003C\u002Fdirectory>\n",[462,3680,3681],{"class":464,"line":750},[462,3682,3683],{},"            \u003CoutputDirectory>Fonts\u003C\u002FoutputDirectory>\n",[462,3685,3686],{"class":464,"line":756},[462,3687,3619],{},[462,3689,3690],{"class":464,"line":762},[462,3691,3594],{},[462,3693,3694],{"class":464,"line":768},[462,3695,3696],{},"            \u003Cdirectory>target\u002Flib\u003C\u002Fdirectory>\n",[462,3698,3699],{"class":464,"line":774},[462,3700,3701],{},"            \u003CoutputDirectory>lib\u003C\u002FoutputDirectory>\n",[462,3703,3704],{"class":464,"line":780},[462,3705,3619],{},[462,3707,3708],{"class":464,"line":786},[462,3709,3710],{},"    \u003C\u002FfileSets>\n",[462,3712,3713],{"class":464,"line":791},[462,3714,3715],{},"\u003C\u002Fassembly>\n",[426,3717,3718,3719,2762],{},"Więcej na temat możliwości archiwizowania można znaleźć ",[977,3720,3723],{"href":3721,"rel":3722},"http:\u002F\u002Fmaven.apache.org\u002Fplugins\u002Fmaven-assembly-plugin\u002Fassembly.html",[981],"tu",[426,3725,3726],{},"Aby wygenerować plik zip należy wydać polecenie:",[452,3728,3732],{"className":3729,"code":3730,"language":3731,"meta":457,"style":457},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","clean install site:site assembly:assembly\n","bash",[459,3733,3734],{"__ignoreMap":457},[462,3735,3736,3740,3744,3747],{"class":464,"line":465},[462,3737,3739],{"class":3738},"sBMFI","clean",[462,3741,3743],{"class":3742},"sfazB"," install",[462,3745,3746],{"class":3742}," site:site",[462,3748,3749],{"class":3742}," assembly:assembly\n",[426,3751,3752],{},"Jeżeli w pliku zip umieszczamy site to gol assembly musi zostać poprzedzony fazą generowania strony.\nPlik taki możemy umieścić na stronie firmowej, bądź na hostingu projekty typu code.google.com czy na github.com w dziale z plikami do pobrania.",[984,3754,3755],{},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}",{"title":457,"searchDepth":471,"depth":471,"links":3757},[],"2011-10-23","Zautomatyzowane wydanie projektu w formie archiwum zip przy pomocy Mavena",{"layout":993},"\u002Fblog\u002F2011-10-23-releasing-archived-maven-archetypes",{"title":3457,"description":3759},"2.blog\u002F2011-10-23-releasing-archived-maven-archetypes","nyRgz872OZHSIyt7AbR2Ro3sAktGf0x7pxKM-J2yVtg",{"id":3766,"title":3767,"authors":409,"badge":409,"body":3768,"date":4015,"description":4016,"extension":991,"image":409,"meta":4017,"navigation":474,"path":4018,"seo":4019,"stem":4020,"__hash__":4021},"posts\u002F2.blog\u002F2011-10-24-hot-deploy-to-remote-tomcat.md","Wdrożenie aplikacji na Tomcata",{"type":423,"value":3769,"toc":4013},[3770,3773,3776,3779,3907,3910,3949,3952,3980,3983,4005,4008,4011],[426,3771,3772],{},"W pewnym punkcie pracy z projektem J2EE, (projekt webowy) dochodzimy do punktu, w którym przychodzi potrzeba umieszczenia go na serwerze czy to kontenerze aplikacji. Po umieszczeniu na serwerze można przetestować jego działanie ale również uruchomić np testy integracyjne.",[426,3774,3775],{},"Ponieważ takich serwerów może istnieć wiele (lokalny, zdalny, klient, …) poszczególne warianty można umieścić np. oddzielnych profilach.",[426,3777,3778],{},"Zdefiniujmy profil, który będzie wykorzystywał plugin cargo, który bedzie łączył się ze zdalnym serwerem tomcat 7.x:",[452,3780,3782],{"className":454,"code":3781,"language":456,"meta":457,"style":457},"\u003Cprofile>\n    \u003Cid>tomcat-remote\u003C\u002Fid>\n    \u003Cbuild>\n        \u003Cplugins>\n            \u003Cplugin>\n                \u003CgroupId>org.codehaus.cargo\u003C\u002FgroupId>\n                \u003CartifactId>cargo-maven2-plugin\u003C\u002FartifactId>\n                \u003Cversion>1.1.3\u003C\u002Fversion>\n                \u003Cconfiguration>\n                    \u003Ccontainer>\n                    \u003CcontainerId>tomcat7x\u003C\u002FcontainerId>\n                    \u003Ctype>remote\u003C\u002Ftype>\n                    \u003C\u002Fcontainer>\n                    \u003Cconfiguration>\n                        \u003Ctype>runtime\u003C\u002Ftype>\n                            \u003Cproperties>\n                            \u003Ccargo.server.settings>my-tomcat-credentials\u003C\u002Fcargo.server.settings>\n                            \u003Ccargo.remote.uri>http:\u002F\u002F10.10.10.105:8080\u002Fmanager\u002Ftext\u003C\u002Fcargo.remote.uri>\n                        \u003C\u002Fproperties>\n                    \u003C\u002Fconfiguration>\n                \u003C\u002Fconfiguration>\n            \u003C\u002Fplugin>\n        \u003C\u002Fplugins>\n    \u003C\u002Fbuild>\n\u003C\u002Fprofile>\n",[459,3783,3784,3789,3794,3798,3803,3808,3813,3818,3823,3828,3833,3838,3843,3848,3853,3858,3863,3868,3873,3878,3883,3888,3893,3898,3902],{"__ignoreMap":457},[462,3785,3786],{"class":464,"line":465},[462,3787,3788],{},"\u003Cprofile>\n",[462,3790,3791],{"class":464,"line":471},[462,3792,3793],{},"    \u003Cid>tomcat-remote\u003C\u002Fid>\n",[462,3795,3796],{"class":464,"line":478},[462,3797,2892],{},[462,3799,3800],{"class":464,"line":484},[462,3801,3802],{},"        \u003Cplugins>\n",[462,3804,3805],{"class":464,"line":489},[462,3806,3807],{},"            \u003Cplugin>\n",[462,3809,3810],{"class":464,"line":495},[462,3811,3812],{},"                \u003CgroupId>org.codehaus.cargo\u003C\u002FgroupId>\n",[462,3814,3815],{"class":464,"line":501},[462,3816,3817],{},"                \u003CartifactId>cargo-maven2-plugin\u003C\u002FartifactId>\n",[462,3819,3820],{"class":464,"line":506},[462,3821,3822],{},"                \u003Cversion>1.1.3\u003C\u002Fversion>\n",[462,3824,3825],{"class":464,"line":512},[462,3826,3827],{},"                \u003Cconfiguration>\n",[462,3829,3830],{"class":464,"line":518},[462,3831,3832],{},"                    \u003Ccontainer>\n",[462,3834,3835],{"class":464,"line":524},[462,3836,3837],{},"                    \u003CcontainerId>tomcat7x\u003C\u002FcontainerId>\n",[462,3839,3840],{"class":464,"line":530},[462,3841,3842],{},"                    \u003Ctype>remote\u003C\u002Ftype>\n",[462,3844,3845],{"class":464,"line":536},[462,3846,3847],{},"                    \u003C\u002Fcontainer>\n",[462,3849,3850],{"class":464,"line":542},[462,3851,3852],{},"                    \u003Cconfiguration>\n",[462,3854,3855],{"class":464,"line":547},[462,3856,3857],{},"                        \u003Ctype>runtime\u003C\u002Ftype>\n",[462,3859,3860],{"class":464,"line":553},[462,3861,3862],{},"                            \u003Cproperties>\n",[462,3864,3865],{"class":464,"line":558},[462,3866,3867],{},"                            \u003Ccargo.server.settings>my-tomcat-credentials\u003C\u002Fcargo.server.settings>\n",[462,3869,3870],{"class":464,"line":564},[462,3871,3872],{},"                            \u003Ccargo.remote.uri>http:\u002F\u002F10.10.10.105:8080\u002Fmanager\u002Ftext\u003C\u002Fcargo.remote.uri>\n",[462,3874,3875],{"class":464,"line":693},[462,3876,3877],{},"                        \u003C\u002Fproperties>\n",[462,3879,3880],{"class":464,"line":699},[462,3881,3882],{},"                    \u003C\u002Fconfiguration>\n",[462,3884,3885],{"class":464,"line":705},[462,3886,3887],{},"                \u003C\u002Fconfiguration>\n",[462,3889,3890],{"class":464,"line":710},[462,3891,3892],{},"            \u003C\u002Fplugin>\n",[462,3894,3895],{"class":464,"line":715},[462,3896,3897],{},"        \u003C\u002Fplugins>\n",[462,3899,3900],{"class":464,"line":721},[462,3901,2932],{},[462,3903,3904],{"class":464,"line":727},[462,3905,3906],{},"\u003C\u002Fprofile>\n",[426,3908,3909],{},"Ostatnią rzeczą jaką należy dodać to dane, które pozwolą pluginowi na uwierzytelnienie na serwerze. Dane te wprowadzimy w pliku settings.xml, aby umieszczać hasel w publicznym miejscu jakim jest repozytorium:",[452,3911,3913],{"className":454,"code":3912,"language":456,"meta":457,"style":457},"\u003Cserver>\n    \u003Cid>my-tomcat-credentials\u003C\u002Fid>\n    \u003Cconfiguration>\n        \u003Ccargo.remote.username>mylogin\u003C\u002Fcargo.remote.username>\n        \u003Ccargo.remote.password>mypassword\u003C\u002Fcargo.remote.password>\n    \u003C\u002Fconfiguration>\n\u003C\u002Fserver>\n",[459,3914,3915,3920,3925,3930,3935,3940,3944],{"__ignoreMap":457},[462,3916,3917],{"class":464,"line":465},[462,3918,3919],{},"\u003Cserver>\n",[462,3921,3922],{"class":464,"line":471},[462,3923,3924],{},"    \u003Cid>my-tomcat-credentials\u003C\u002Fid>\n",[462,3926,3927],{"class":464,"line":478},[462,3928,3929],{},"    \u003Cconfiguration>\n",[462,3931,3932],{"class":464,"line":484},[462,3933,3934],{},"        \u003Ccargo.remote.username>mylogin\u003C\u002Fcargo.remote.username>\n",[462,3936,3937],{"class":464,"line":489},[462,3938,3939],{},"        \u003Ccargo.remote.password>mypassword\u003C\u002Fcargo.remote.password>\n",[462,3941,3942],{"class":464,"line":495},[462,3943,3521],{},[462,3945,3946],{"class":464,"line":501},[462,3947,3948],{},"\u003C\u002Fserver>\n",[426,3950,3951],{},"Tu należy wyjaśnić kilka kwesti:",[439,3953,3954,3957,3960,3963],{},[442,3955,3956],{},"Plugin cargo pozwala na zarządzanie serwerem \u002F kontenerem poprzez: uruchamianie, zatrzymywanie, undeploy, deploy i parę innych",[442,3958,3959],{},"Zarządzać można serwerem zainstalowanym lokalnie, zdalnym oraz można podać link do archiwum zip na stronie internetowej z dyrektywą aby plugin sam zainstalował serwer w podanej lokalizacji. Oczywiście projekt można deployować na serwerach zatrzymanych jak i uruchomionych.",[442,3961,3962],{},"Url do tomcata w wersji 7.x należy podać do managera tekstowego.",[442,3964,3965,3966,3969,3970,3973,3974,3977,3978,2762],{},"Aby móc zarządzać kontenerem należy użytkownikowi, za pomocą którego łączymy się z serwerem dodać uprawnienie ",[459,3967,3968],{},"manager-script",". Aby to zrobić należy wyedytować plik ",[459,3971,3972],{},"tomcat-users.xml"," znajdujący się w folderze ",[459,3975,3976],{},"%TOMCAT_DIR%\u002Fconf\u002Ftomcat-users.xml"," a następnie dodać po przecinku w roles wskazanego użytkownika ",[459,3979,3968],{},[426,3981,3982],{},"Deploy pliku war następuje po wydaniu polecenia:",[452,3984,3986],{"className":3729,"code":3985,"language":3731,"meta":457,"style":457},"mvn -Ptomcat-remote clean verify org.codehaus.cargo:cargo-maven2-plugin:deploy\n",[459,3987,3988],{"__ignoreMap":457},[462,3989,3990,3993,3996,3999,4002],{"class":464,"line":465},[462,3991,3992],{"class":3738},"mvn",[462,3994,3995],{"class":3742}," -Ptomcat-remote",[462,3997,3998],{"class":3742}," clean",[462,4000,4001],{"class":3742}," verify",[462,4003,4004],{"class":3742}," org.codehaus.cargo:cargo-maven2-plugin:deploy\n",[426,4006,4007],{},"Po parametrze -P podajemy nazwę profilu, który jest aktywowany podczas uruchomienia. Jeżeli nie zostanie wskazany domyślne parametry zostaną wykorzystane a wtedy na 90% zostanie rzucony wyjątek.\nOczywiście zaprezentowany przykład zadziała jedynie gdy serwer jest uruchomiony i nie istnieje wcześniej zdeployowany aktualny projekt.",[426,4009,4010],{},"Serwer należy uruchomić, przejść do managera aplikacji a następnie wykonać undeploy.",[984,4012,3755],{},{"title":457,"searchDepth":471,"depth":471,"links":4014},[],"2011-10-24","Zautomatyzowane wdrożenia aplikacji na serwer Tomcat z uzyciem Mavena i pluginu Cargo",{"layout":993},"\u002Fblog\u002F2011-10-24-hot-deploy-to-remote-tomcat",{"title":3767,"description":4016},"2.blog\u002F2011-10-24-hot-deploy-to-remote-tomcat","hFAjEu5mP4AHbwcjosiUzhNUXPqTU8h-V7T1fgJ_Uv0",{"id":4023,"title":4024,"authors":409,"badge":409,"body":4025,"date":4149,"description":4150,"extension":991,"image":409,"meta":4151,"navigation":474,"path":4152,"seo":4153,"stem":4154,"__hash__":4155},"posts\u002F2.blog\u002F2011-12-15-introduction-to-jetty.md","Jetty - poręczny serwerek",{"type":423,"value":4026,"toc":4147},[4027,4030,4071,4085,4092,4099,4113,4116,4128,4131,4142,4145],[426,4028,4029],{},"W trakcie tworzenia aplikacji internetowych przychodzi moment kiedy należy go umieścić na jakimś serwerze. Do dyspozycji mamy naprawdę szeroką pulę począwszy od lekkiego Tomcata po serwery aplikacji takie jak GlassFish czy JBoss.\nDzisiaj zaprezentujemy malutki i zgrabniutki kontener serwletów Jetty. Jego główną zaletą nad pozostałymi jest banalna konfiguracja oraz szybkość uruchamiania.\nKonfiguracja całości w projekcie budowanym za pomocą Mavena sprowadza się do dodania następującego plugina w pliku pom.xml:",[452,4031,4033],{"className":454,"code":4032,"language":456,"meta":457,"style":457},"\u003Cplugin>\n    \u003CgroupId>org.mortbay.jetty\u003C\u002FgroupId>\n    \u003CartifactId>maven-jetty-plugin\u003C\u002FartifactId>\n    \u003Cconfiguration>\n        \u003CscanIntervalSeconds>10\u003C\u002FscanIntervalSeconds>\n        \u003CcontextPath>\u002F\u003C\u002FcontextPath>\n    \u003C\u002Fconfiguration>\n\u003C\u002Fplugin>\n",[459,4034,4035,4039,4044,4049,4053,4058,4063,4067],{"__ignoreMap":457},[462,4036,4037],{"class":464,"line":465},[462,4038,3486],{},[462,4040,4041],{"class":464,"line":471},[462,4042,4043],{},"    \u003CgroupId>org.mortbay.jetty\u003C\u002FgroupId>\n",[462,4045,4046],{"class":464,"line":478},[462,4047,4048],{},"    \u003CartifactId>maven-jetty-plugin\u003C\u002FartifactId>\n",[462,4050,4051],{"class":464,"line":484},[462,4052,3929],{},[462,4054,4055],{"class":464,"line":489},[462,4056,4057],{},"        \u003CscanIntervalSeconds>10\u003C\u002FscanIntervalSeconds>\n",[462,4059,4060],{"class":464,"line":495},[462,4061,4062],{},"        \u003CcontextPath>\u002F\u003C\u002FcontextPath>\n",[462,4064,4065],{"class":464,"line":501},[462,4066,3521],{},[462,4068,4069],{"class":464,"line":506},[462,4070,3526],{},[426,4072,4073,4074,4077,4078,4081,4082,2762],{},"Uruchomienie serwera odbywa się za pomocą: ",[459,4075,4076],{},"jetty:run"," bądź ",[459,4079,4080],{},"jetty:run-exploded",". Przed uruchomieniem nastąpi build projektu a następnie jego automatyczne wdrożenie (deploy) pod kontekstem \u002F. Jeżeli wszystko zakończyło się powodzeniem aplikacja staje się dostępna pod adresem: ",[459,4083,4084],{},"localhost:8080",[426,4086,4087,4088,4091],{},"Bardzo przydatną funkcjonalnością w każdym serwerze jest tzw. ",[459,4089,4090],{},"hot-deploy",". Jest to możliwość serwera do wdrożenia aplikacji na uruchomionym serwerze. Co pewien czas skanowany jest kod i jeżeli ten się zmienił to wówczas następuje redeploy.",[426,4093,4094,4095,4098],{},"Tworząc typowy projekt wszystko odbywa się automatycznie w interwale podanym w parametrze ",[459,4096,4097],{},"scanIntervalSeconds",", jednak tworząc projekt GWT częścią efektu wyjściowego jest skompilowany do JavaScript-u kod kliencki, dlatego aby zobaczyć zmiany należy najlepiej skompilować cały projekt od nowa. Zwykle w tym celu wykonuje się polecenie",[452,4100,4102],{"className":3729,"code":4101,"language":3731,"meta":457,"style":457},"mvn clean install\n",[459,4103,4104],{"__ignoreMap":457},[462,4105,4106,4108,4110],{"class":464,"line":465},[462,4107,3992],{"class":3738},[462,4109,3998],{"class":3742},[462,4111,4112],{"class":3742}," install\n",[426,4114,4115],{},"ale to nie zadziała, gdy serwer jest uruchomiony, ponieważ serwer tworzy podfolder work w folderze target, który jest zablokowany i każda próba zakończy się niepowodzeniem.\nAby redeployować projekt GWT należy uruchomić go poleceniem:",[452,4117,4119],{"className":3729,"code":4118,"language":3731,"meta":457,"style":457},"mvn jetty:run-exploded\n",[459,4120,4121],{"__ignoreMap":457},[462,4122,4123,4125],{"class":464,"line":465},[462,4124,3992],{"class":3738},[462,4126,4127],{"class":3742}," jetty:run-exploded\n",[426,4129,4130],{},"a następnie jeżeli chcemy odświeżyć część kliencką wykonujemy kompilację bez kasowania folderu target:",[452,4132,4134],{"className":3729,"code":4133,"language":3731,"meta":457,"style":457},"mvn install\n",[459,4135,4136],{"__ignoreMap":457},[462,4137,4138,4140],{"class":464,"line":465},[462,4139,3992],{"class":3738},[462,4141,4112],{"class":3742},[426,4143,4144],{},"W trakcie kompilacji co 10 sekund serwer będzie deployował projekt a po zakończeniu kompilacji można odświeżyć stronę z wprowadzonymi zmianami.",[984,4146,3755],{},{"title":457,"searchDepth":471,"depth":471,"links":4148},[],"2011-12-15","Jetty jako narzędzie ułatwiające życie programistom Java",{"layout":993},"\u002Fblog\u002F2011-12-15-introduction-to-jetty",{"title":4024,"description":4150},"2.blog\u002F2011-12-15-introduction-to-jetty","pmlwDUNnMUq4q8ARK0isJYf_Q3fUdbSaq-IjDPUHTm0",{"id":4157,"title":4158,"authors":409,"badge":409,"body":4159,"date":5573,"description":5574,"extension":991,"image":409,"meta":5575,"navigation":474,"path":5576,"seo":5577,"stem":5578,"__hash__":5579},"posts\u002F2.blog\u002F2012-02-02-fast-track-to-hibernate.md","Podstawowy projekt z użyciem Hibernate",{"type":423,"value":4160,"toc":5571},[4161,4164,4167,4170,4293,4296,4299,4378,4381,4637,4640,4652,4655,4658,4763,4766,4769,4848,4851,4911,4914,4917,5131,5138,5145,5172,5175,5178,5388,5391,5568],[426,4162,4163],{},"W dzisiejszym poście zaprezentujemy jak stworzyć projekt, który może stanowić wejście dla przyszłych projektów wykorzystujących Hibernate oraz Mavena. Do zamockowania bazy danych posłużymy się wbudowaną (embeded) bazą danych – Derby.",[426,4165,4166],{},"##Nowy projekt",[426,4168,4169],{},"Nalezy utworzyć nowy projekt za pomoca polecenia:",[452,4171,4173],{"className":3729,"code":4172,"language":3731,"meta":457,"style":457},"mvn -DarchetypeGroupId=org.apache.maven.archetypes\n-DarchetypeArtifactId=maven-archetype-quickstart\n-DarchetypeVersion=1.1\n-DarchetypeRepository=http:\u002F\u002Frepo1.maven.org\u002Fmaven2\n-DgroupId=pl.xperios\n-DartifactId=HibernateMavenStarter\n-Dversion=1.0-SNAPSHOT\n-Dpackage=pl.xperios.HibernateMavenStarter\n-Dbasedir=C:\\\\Projects\\\\Starters\n-Darchetype.interactive=false –batch-mode archetype:generate\n",[459,4174,4175,4182,4195,4205,4215,4225,4235,4245,4255,4276],{"__ignoreMap":457},[462,4176,4177,4179],{"class":464,"line":465},[462,4178,3992],{"class":3738},[462,4180,4181],{"class":3742}," -DarchetypeGroupId=org.apache.maven.archetypes\n",[462,4183,4184,4188,4192],{"class":464,"line":471},[462,4185,4187],{"class":4186},"sTEyZ","-DarchetypeArtifactId",[462,4189,4191],{"class":4190},"sMK4o","=",[462,4193,4194],{"class":3742},"maven-archetype-quickstart\n",[462,4196,4197,4200,4202],{"class":464,"line":478},[462,4198,4199],{"class":4186},"-DarchetypeVersion",[462,4201,4191],{"class":4190},[462,4203,4204],{"class":3742},"1.1\n",[462,4206,4207,4210,4212],{"class":464,"line":484},[462,4208,4209],{"class":4186},"-DarchetypeRepository",[462,4211,4191],{"class":4190},[462,4213,4214],{"class":3742},"http:\u002F\u002Frepo1.maven.org\u002Fmaven2\n",[462,4216,4217,4220,4222],{"class":464,"line":489},[462,4218,4219],{"class":4186},"-DgroupId",[462,4221,4191],{"class":4190},[462,4223,4224],{"class":3742},"pl.xperios\n",[462,4226,4227,4230,4232],{"class":464,"line":495},[462,4228,4229],{"class":4186},"-DartifactId",[462,4231,4191],{"class":4190},[462,4233,4234],{"class":3742},"HibernateMavenStarter\n",[462,4236,4237,4240,4242],{"class":464,"line":501},[462,4238,4239],{"class":4186},"-Dversion",[462,4241,4191],{"class":4190},[462,4243,4244],{"class":3742},"1.0-SNAPSHOT\n",[462,4246,4247,4250,4252],{"class":464,"line":506},[462,4248,4249],{"class":4186},"-Dpackage",[462,4251,4191],{"class":4190},[462,4253,4254],{"class":3742},"pl.xperios.HibernateMavenStarter\n",[462,4256,4257,4260,4262,4265,4268,4271,4273],{"class":464,"line":512},[462,4258,4259],{"class":4186},"-Dbasedir",[462,4261,4191],{"class":4190},[462,4263,4264],{"class":3742},"C:",[462,4266,4267],{"class":4186},"\\\\",[462,4269,4270],{"class":3742},"Projects",[462,4272,4267],{"class":4186},[462,4274,4275],{"class":3742},"Starters\n",[462,4277,4278,4281,4283,4287,4290],{"class":464,"line":518},[462,4279,4280],{"class":3738},"-Darchetype.interactive",[462,4282,4191],{"class":3742},[462,4284,4286],{"class":4285},"s2Zo4","false",[462,4288,4289],{"class":3742}," –batch-mode",[462,4291,4292],{"class":3742}," archetype:generate\n",[426,4294,4295],{},"##Konfiguracja zależności",[426,4297,4298],{},"Po stworzeniu struktury projektu należy dodać zależności Hibernate. Ponieważ nie występują w repozytorium centralnym najpierw należy dodać odpowiednie repozytoria do pliku pom.xml:",[452,4300,4302],{"className":454,"code":4301,"language":456,"meta":457,"style":457},"    \u003Crepositories>\n        \u003Crepository>\n            \u003Cid>sonatype-snapshots\u003C\u002Fid>\n            \u003Cname>Sonatype Snapshots\u003C\u002Fname>\n            \u003Curl>https:\u002F\u002Foss.sonatype.org\u002Fcontent\u002Frepositories\u002Fsnapshots\u002F\u003C\u002Furl>\n            \u003Csnapshots>\n                \u003Cenabled>true\u003C\u002Fenabled>\n            \u003C\u002Fsnapshots>\n        \u003C\u002Frepository>\n        \u003Crepository>\n            \u003Curl>http:\u002F\u002Fdownload.java.net\u002Fmaven\u002F2\u002F\u003C\u002Furl>\n            \u003Cid>download.java.net\u003C\u002Fid>\n            \u003Clayout>default\u003C\u002Flayout>\n            \u003Cname>Hibernate support\u003C\u002Fname>\n        \u003C\u002Frepository>\n    \u003C\u002Frepositories>\n",[459,4303,4304,4308,4312,4317,4322,4327,4332,4337,4342,4346,4350,4355,4360,4365,4370,4374],{"__ignoreMap":457},[462,4305,4306],{"class":464,"line":465},[462,4307,2784],{},[462,4309,4310],{"class":464,"line":471},[462,4311,2789],{},[462,4313,4314],{"class":464,"line":478},[462,4315,4316],{},"            \u003Cid>sonatype-snapshots\u003C\u002Fid>\n",[462,4318,4319],{"class":464,"line":484},[462,4320,4321],{},"            \u003Cname>Sonatype Snapshots\u003C\u002Fname>\n",[462,4323,4324],{"class":464,"line":489},[462,4325,4326],{},"            \u003Curl>https:\u002F\u002Foss.sonatype.org\u002Fcontent\u002Frepositories\u002Fsnapshots\u002F\u003C\u002Furl>\n",[462,4328,4329],{"class":464,"line":495},[462,4330,4331],{},"            \u003Csnapshots>\n",[462,4333,4334],{"class":464,"line":501},[462,4335,4336],{},"                \u003Cenabled>true\u003C\u002Fenabled>\n",[462,4338,4339],{"class":464,"line":506},[462,4340,4341],{},"            \u003C\u002Fsnapshots>\n",[462,4343,4344],{"class":464,"line":512},[462,4345,2809],{},[462,4347,4348],{"class":464,"line":518},[462,4349,2789],{},[462,4351,4352],{"class":464,"line":524},[462,4353,4354],{},"            \u003Curl>http:\u002F\u002Fdownload.java.net\u002Fmaven\u002F2\u002F\u003C\u002Furl>\n",[462,4356,4357],{"class":464,"line":530},[462,4358,4359],{},"            \u003Cid>download.java.net\u003C\u002Fid>\n",[462,4361,4362],{"class":464,"line":536},[462,4363,4364],{},"            \u003Clayout>default\u003C\u002Flayout>\n",[462,4366,4367],{"class":464,"line":542},[462,4368,4369],{},"            \u003Cname>Hibernate support\u003C\u002Fname>\n",[462,4371,4372],{"class":464,"line":547},[462,4373,2809],{},[462,4375,4376],{"class":464,"line":553},[462,4377,2814],{},[426,4379,4380],{},"Od tej pory do projektu możemy dołączać również zależności, które nie znajdują się w repozytorium centralnym:",[452,4382,4384],{"className":454,"code":4383,"language":456,"meta":457,"style":457},"\u003Cdependencies>\n        \u003Cdependency>\n            \u003CgroupId>junit\u003C\u002FgroupId>\n            \u003CartifactId>junit\u003C\u002FartifactId>\n            \u003Cversion>3.8.1\u003C\u002Fversion>\n            \u003Cscope>test\u003C\u002Fscope>\n        \u003C\u002Fdependency>\n        \u003Cdependency>\n            \u003CgroupId>log4j\u003C\u002FgroupId>\n            \u003CartifactId>log4j\u003C\u002FartifactId>\n            \u003Cversion>1.2.16\u003C\u002Fversion>\n        \u003C\u002Fdependency>\n        \u003Cdependency>\n            \u003CgroupId>org.slf4j\u003C\u002FgroupId>\n            \u003CartifactId>slf4j-log4j12\u003C\u002FartifactId>\n            \u003Cversion>1.5.6\u003C\u002Fversion>\n        \u003C\u002Fdependency>\n        \u003Cdependency>\n            \u003CgroupId>org.hibernate\u003C\u002FgroupId>\n            \u003CartifactId>hibernate\u003C\u002FartifactId>\n            \u003Cversion>3.2.5.ga\u003C\u002Fversion>\n        \u003C\u002Fdependency>\n        \u003Cdependency>\n            \u003CgroupId>org.hibernate\u003C\u002FgroupId>\n            \u003CartifactId>hibernate-entitymanager\u003C\u002FartifactId>\n            \u003Cversion>3.3.2.GA\u003C\u002Fversion>\n        \u003C\u002Fdependency>\n        \u003Cdependency>\n            \u003CgroupId>org.hibernate\u003C\u002FgroupId>\n            \u003CartifactId>hibernate-validator\u003C\u002FartifactId>\n            \u003Cversion>4.1.0.Final\u003C\u002Fversion>\n        \u003C\u002Fdependency>\n        \u003Cdependency>\n            \u003CgroupId>javax.sql\u003C\u002FgroupId>\n            \u003CartifactId>jdbc-stdext\u003C\u002FartifactId>\n            \u003Cversion>2.0\u003C\u002Fversion>\n        \u003C\u002Fdependency>\n        \u003Cdependency>\n            \u003CgroupId>javax.transaction\u003C\u002FgroupId>\n            \u003CartifactId>jta\u003C\u002FartifactId>\n            \u003Cversion>1.0.1B\u003C\u002Fversion>\n        \u003C\u002Fdependency>\n        \u003Cdependency>\n            \u003CgroupId>org.hibernate\u003C\u002FgroupId>\n            \u003CartifactId>ejb3-persistence\u003C\u002FartifactId>\n            \u003Cversion>1.0.1.GA\u003C\u002Fversion>\n        \u003C\u002Fdependency>\n        \u003Cdependency>\n            \u003CgroupId>org.apache.derby\u003C\u002FgroupId>\n            \u003CartifactId>derbyclient\u003C\u002FartifactId>\n            \u003Cversion>10.8.1.2\u003C\u002Fversion>\n        \u003C\u002Fdependency>\n    \u003C\u002Fdependencies>\n",[459,4385,4386,4391,4396,4401,4406,4411,4416,4421,4425,4430,4435,4440,4444,4448,4453,4458,4463,4467,4471,4476,4481,4486,4490,4494,4498,4503,4508,4512,4516,4520,4525,4530,4534,4538,4543,4548,4553,4557,4561,4566,4571,4576,4580,4584,4588,4593,4598,4603,4608,4614,4620,4626,4631],{"__ignoreMap":457},[462,4387,4388],{"class":464,"line":465},[462,4389,4390],{},"\u003Cdependencies>\n",[462,4392,4393],{"class":464,"line":471},[462,4394,4395],{},"        \u003Cdependency>\n",[462,4397,4398],{"class":464,"line":478},[462,4399,4400],{},"            \u003CgroupId>junit\u003C\u002FgroupId>\n",[462,4402,4403],{"class":464,"line":484},[462,4404,4405],{},"            \u003CartifactId>junit\u003C\u002FartifactId>\n",[462,4407,4408],{"class":464,"line":489},[462,4409,4410],{},"            \u003Cversion>3.8.1\u003C\u002Fversion>\n",[462,4412,4413],{"class":464,"line":495},[462,4414,4415],{},"            \u003Cscope>test\u003C\u002Fscope>\n",[462,4417,4418],{"class":464,"line":501},[462,4419,4420],{},"        \u003C\u002Fdependency>\n",[462,4422,4423],{"class":464,"line":506},[462,4424,4395],{},[462,4426,4427],{"class":464,"line":512},[462,4428,4429],{},"            \u003CgroupId>log4j\u003C\u002FgroupId>\n",[462,4431,4432],{"class":464,"line":518},[462,4433,4434],{},"            \u003CartifactId>log4j\u003C\u002FartifactId>\n",[462,4436,4437],{"class":464,"line":524},[462,4438,4439],{},"            \u003Cversion>1.2.16\u003C\u002Fversion>\n",[462,4441,4442],{"class":464,"line":530},[462,4443,4420],{},[462,4445,4446],{"class":464,"line":536},[462,4447,4395],{},[462,4449,4450],{"class":464,"line":542},[462,4451,4452],{},"            \u003CgroupId>org.slf4j\u003C\u002FgroupId>\n",[462,4454,4455],{"class":464,"line":547},[462,4456,4457],{},"            \u003CartifactId>slf4j-log4j12\u003C\u002FartifactId>\n",[462,4459,4460],{"class":464,"line":553},[462,4461,4462],{},"            \u003Cversion>1.5.6\u003C\u002Fversion>\n",[462,4464,4465],{"class":464,"line":558},[462,4466,4420],{},[462,4468,4469],{"class":464,"line":564},[462,4470,4395],{},[462,4472,4473],{"class":464,"line":693},[462,4474,4475],{},"            \u003CgroupId>org.hibernate\u003C\u002FgroupId>\n",[462,4477,4478],{"class":464,"line":699},[462,4479,4480],{},"            \u003CartifactId>hibernate\u003C\u002FartifactId>\n",[462,4482,4483],{"class":464,"line":705},[462,4484,4485],{},"            \u003Cversion>3.2.5.ga\u003C\u002Fversion>\n",[462,4487,4488],{"class":464,"line":710},[462,4489,4420],{},[462,4491,4492],{"class":464,"line":715},[462,4493,4395],{},[462,4495,4496],{"class":464,"line":721},[462,4497,4475],{},[462,4499,4500],{"class":464,"line":727},[462,4501,4502],{},"            \u003CartifactId>hibernate-entitymanager\u003C\u002FartifactId>\n",[462,4504,4505],{"class":464,"line":732},[462,4506,4507],{},"            \u003Cversion>3.3.2.GA\u003C\u002Fversion>\n",[462,4509,4510],{"class":464,"line":738},[462,4511,4420],{},[462,4513,4514],{"class":464,"line":744},[462,4515,4395],{},[462,4517,4518],{"class":464,"line":750},[462,4519,4475],{},[462,4521,4522],{"class":464,"line":756},[462,4523,4524],{},"            \u003CartifactId>hibernate-validator\u003C\u002FartifactId>\n",[462,4526,4527],{"class":464,"line":762},[462,4528,4529],{},"            \u003Cversion>4.1.0.Final\u003C\u002Fversion>\n",[462,4531,4532],{"class":464,"line":768},[462,4533,4420],{},[462,4535,4536],{"class":464,"line":774},[462,4537,4395],{},[462,4539,4540],{"class":464,"line":780},[462,4541,4542],{},"            \u003CgroupId>javax.sql\u003C\u002FgroupId>\n",[462,4544,4545],{"class":464,"line":786},[462,4546,4547],{},"            \u003CartifactId>jdbc-stdext\u003C\u002FartifactId>\n",[462,4549,4550],{"class":464,"line":791},[462,4551,4552],{},"            \u003Cversion>2.0\u003C\u002Fversion>\n",[462,4554,4555],{"class":464,"line":797},[462,4556,4420],{},[462,4558,4559],{"class":464,"line":803},[462,4560,4395],{},[462,4562,4563],{"class":464,"line":808},[462,4564,4565],{},"            \u003CgroupId>javax.transaction\u003C\u002FgroupId>\n",[462,4567,4568],{"class":464,"line":2107},[462,4569,4570],{},"            \u003CartifactId>jta\u003C\u002FartifactId>\n",[462,4572,4573],{"class":464,"line":2112},[462,4574,4575],{},"            \u003Cversion>1.0.1B\u003C\u002Fversion>\n",[462,4577,4578],{"class":464,"line":2117},[462,4579,4420],{},[462,4581,4582],{"class":464,"line":2431},[462,4583,4395],{},[462,4585,4586],{"class":464,"line":2437},[462,4587,4475],{},[462,4589,4590],{"class":464,"line":2443},[462,4591,4592],{},"            \u003CartifactId>ejb3-persistence\u003C\u002FartifactId>\n",[462,4594,4595],{"class":464,"line":2448},[462,4596,4597],{},"            \u003Cversion>1.0.1.GA\u003C\u002Fversion>\n",[462,4599,4601],{"class":464,"line":4600},47,[462,4602,4420],{},[462,4604,4606],{"class":464,"line":4605},48,[462,4607,4395],{},[462,4609,4611],{"class":464,"line":4610},49,[462,4612,4613],{},"            \u003CgroupId>org.apache.derby\u003C\u002FgroupId>\n",[462,4615,4617],{"class":464,"line":4616},50,[462,4618,4619],{},"            \u003CartifactId>derbyclient\u003C\u002FartifactId>\n",[462,4621,4623],{"class":464,"line":4622},51,[462,4624,4625],{},"            \u003Cversion>10.8.1.2\u003C\u002Fversion>\n",[462,4627,4629],{"class":464,"line":4628},52,[462,4630,4420],{},[462,4632,4634],{"class":464,"line":4633},53,[462,4635,4636],{},"    \u003C\u002Fdependencies>\n",[426,4638,4639],{},"Po zapisaniu projektu i pierwszej kompilacji zostaną pobrane zależności do lokalnego repozytorium. W tym celu należy wydać polecenie:",[452,4641,4642],{"className":3729,"code":4101,"language":3731,"meta":457,"style":457},[459,4643,4644],{"__ignoreMap":457},[462,4645,4646,4648,4650],{"class":464,"line":465},[462,4647,3992],{"class":3738},[462,4649,3998],{"class":3742},[462,4651,4112],{"class":3742},[426,4653,4654],{},"##Klasa pomocnicza HibernateUtil",[426,4656,4657],{},"Pracę zaczynamy od stworzenia specjalnej klasy narzędziowej, która inicjuje konfigurację oraz pozwala na dostęp do usług Hibernate poprzez metody statyczne:",[452,4659,4661],{"className":598,"code":4660,"language":600,"meta":457,"style":457},"package pl.xperios.hibernatestarter;\n\nimport org.hibernate.cfg.AnnotationConfiguration;\nimport org.hibernate.SessionFactory;\n\npublic class HibernateUtil {\n\n    private static final SessionFactory sessionFactory;\n\n    static {\n        try {\n            sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();\n        } catch (Throwable ex) {\n            System.err.println(\"Initial SessionFactory creation failed.\" + ex);\n            throw new ExceptionInInitializerError(ex);\n        }\n    }\n\n    public static SessionFactory getSessionFactory() {\n        return sessionFactory;\n    }\n}\n",[459,4662,4663,4668,4672,4677,4682,4686,4691,4695,4700,4704,4709,4713,4718,4723,4728,4733,4737,4741,4745,4750,4755,4759],{"__ignoreMap":457},[462,4664,4665],{"class":464,"line":465},[462,4666,4667],{},"package pl.xperios.hibernatestarter;\n",[462,4669,4670],{"class":464,"line":471},[462,4671,475],{"emptyLinePlaceholder":474},[462,4673,4674],{"class":464,"line":478},[462,4675,4676],{},"import org.hibernate.cfg.AnnotationConfiguration;\n",[462,4678,4679],{"class":464,"line":484},[462,4680,4681],{},"import org.hibernate.SessionFactory;\n",[462,4683,4684],{"class":464,"line":489},[462,4685,475],{"emptyLinePlaceholder":474},[462,4687,4688],{"class":464,"line":495},[462,4689,4690],{},"public class HibernateUtil {\n",[462,4692,4693],{"class":464,"line":501},[462,4694,475],{"emptyLinePlaceholder":474},[462,4696,4697],{"class":464,"line":506},[462,4698,4699],{},"    private static final SessionFactory sessionFactory;\n",[462,4701,4702],{"class":464,"line":512},[462,4703,475],{"emptyLinePlaceholder":474},[462,4705,4706],{"class":464,"line":518},[462,4707,4708],{},"    static {\n",[462,4710,4711],{"class":464,"line":524},[462,4712,1662],{},[462,4714,4715],{"class":464,"line":530},[462,4716,4717],{},"            sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();\n",[462,4719,4720],{"class":464,"line":536},[462,4721,4722],{},"        } catch (Throwable ex) {\n",[462,4724,4725],{"class":464,"line":542},[462,4726,4727],{},"            System.err.println(\"Initial SessionFactory creation failed.\" + ex);\n",[462,4729,4730],{"class":464,"line":547},[462,4731,4732],{},"            throw new ExceptionInInitializerError(ex);\n",[462,4734,4735],{"class":464,"line":553},[462,4736,1077],{},[462,4738,4739],{"class":464,"line":558},[462,4740,702],{},[462,4742,4743],{"class":464,"line":564},[462,4744,475],{"emptyLinePlaceholder":474},[462,4746,4747],{"class":464,"line":693},[462,4748,4749],{},"    public static SessionFactory getSessionFactory() {\n",[462,4751,4752],{"class":464,"line":699},[462,4753,4754],{},"        return sessionFactory;\n",[462,4756,4757],{"class":464,"line":705},[462,4758,702],{},[462,4760,4761],{"class":464,"line":710},[462,4762,811],{},[426,4764,4765],{},"##Konfiguracja Hibernate",[426,4767,4768],{},"Powyższa klasa inicjuje konfigurację opartą na anotacjach a następnie odczytuje konfiguracje z jednego z możliwych źródeł. My posłużymy się plikiem konfiguracyjnym zawartym w pliku xml. W tym celu należy stworzyć plik hibernate.cfg.xml w folderze src\u002Fmain\u002Fresources o następującej treści:",[452,4770,4772],{"className":454,"code":4771,"language":456,"meta":457,"style":457},"\u003C?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\u003C!DOCTYPE hibernate-configuration PUBLIC \"-\u002F\u002FHibernate\u002FHibernate Configuration DTD 3.0\u002F\u002FEN\" \"http:\u002F\u002Fhibernate.sourceforge.net\u002Fhibernate-configuration-3.0.dtd\">\n\u003Chibernate-configuration>\n  \u003Csession-factory>\n    \u003Cproperty name=\"hibernate.dialect\">org.hibernate.dialect.DerbyDialect\u003C\u002Fproperty>\n    \u003Cproperty name=\"hibernate.connection.driver_class\">org.apache.derby.jdbc.ClientDriver\u003C\u002Fproperty>\n    \u003Cproperty name=\"hibernate.connection.url\">jdbc:derby:\u002F\u002Flocalhost:1527\u002Fsample\u003C\u002Fproperty>\n    \u003Cproperty name=\"hibernate.connection.username\">app\u003C\u002Fproperty>\n    \u003Cproperty name=\"hibernate.connection.password\">app\u003C\u002Fproperty>\n    \u003Cproperty name=\"hibernate.show_sql\">true\u003C\u002Fproperty>\n    \u003Cproperty name=\"hibernate.hbm2ddl.auto\">create-drop\u003C\u002Fproperty>\n    \u003Cproperty name=\"hibernate.current_session_context_class\">thread\u003C\u002Fproperty>\n    \u003Cproperty name=\"hibernate.transaction.auto_close_session\">true\u003C\u002Fproperty>\n  \u003C\u002Fsession-factory>\n\u003C\u002Fhibernate-configuration>\n",[459,4773,4774,4778,4783,4788,4793,4798,4803,4808,4813,4818,4823,4828,4833,4838,4843],{"__ignoreMap":457},[462,4775,4776],{"class":464,"line":465},[462,4777,468],{},[462,4779,4780],{"class":464,"line":471},[462,4781,4782],{},"\u003C!DOCTYPE hibernate-configuration PUBLIC \"-\u002F\u002FHibernate\u002FHibernate Configuration DTD 3.0\u002F\u002FEN\" \"http:\u002F\u002Fhibernate.sourceforge.net\u002Fhibernate-configuration-3.0.dtd\">\n",[462,4784,4785],{"class":464,"line":478},[462,4786,4787],{},"\u003Chibernate-configuration>\n",[462,4789,4790],{"class":464,"line":484},[462,4791,4792],{},"  \u003Csession-factory>\n",[462,4794,4795],{"class":464,"line":489},[462,4796,4797],{},"    \u003Cproperty name=\"hibernate.dialect\">org.hibernate.dialect.DerbyDialect\u003C\u002Fproperty>\n",[462,4799,4800],{"class":464,"line":495},[462,4801,4802],{},"    \u003Cproperty name=\"hibernate.connection.driver_class\">org.apache.derby.jdbc.ClientDriver\u003C\u002Fproperty>\n",[462,4804,4805],{"class":464,"line":501},[462,4806,4807],{},"    \u003Cproperty name=\"hibernate.connection.url\">jdbc:derby:\u002F\u002Flocalhost:1527\u002Fsample\u003C\u002Fproperty>\n",[462,4809,4810],{"class":464,"line":506},[462,4811,4812],{},"    \u003Cproperty name=\"hibernate.connection.username\">app\u003C\u002Fproperty>\n",[462,4814,4815],{"class":464,"line":512},[462,4816,4817],{},"    \u003Cproperty name=\"hibernate.connection.password\">app\u003C\u002Fproperty>\n",[462,4819,4820],{"class":464,"line":518},[462,4821,4822],{},"    \u003Cproperty name=\"hibernate.show_sql\">true\u003C\u002Fproperty>\n",[462,4824,4825],{"class":464,"line":524},[462,4826,4827],{},"    \u003Cproperty name=\"hibernate.hbm2ddl.auto\">create-drop\u003C\u002Fproperty>\n",[462,4829,4830],{"class":464,"line":530},[462,4831,4832],{},"    \u003Cproperty name=\"hibernate.current_session_context_class\">thread\u003C\u002Fproperty>\n",[462,4834,4835],{"class":464,"line":536},[462,4836,4837],{},"    \u003Cproperty name=\"hibernate.transaction.auto_close_session\">true\u003C\u002Fproperty>\n",[462,4839,4840],{"class":464,"line":542},[462,4841,4842],{},"  \u003C\u002Fsession-factory>\n",[462,4844,4845],{"class":464,"line":547},[462,4846,4847],{},"\u003C\u002Fhibernate-configuration>\n",[426,4849,4850],{},"Powyższy plik definiuje między innymi:",[439,4852,4853,4856,4862,4868,4874,4880,4886,4892,4898,4905],{},[442,4854,4855],{},"połączenie z bazą danych:",[442,4857,4858,4859],{},"sterownik ",[459,4860,4861],{},"hibernate.connection.driver_class",[442,4863,4864,4865],{},"url ",[459,4866,4867],{},"hibernate.connection.url",[442,4869,4870,4871],{},"login ",[459,4872,4873],{},"hibernate.connection.username",[442,4875,4876,4877],{},"hasło ",[459,4878,4879],{},"hibernate.connection.password",[442,4881,4882,4883],{},"dialekt ",[459,4884,4885],{},"hibernate.dialect",[442,4887,4888,4889],{},"pokazywanie w konsoli wykonywanych zapytań do bazy ",[459,4890,4891],{},"hibernate.show_sql",[442,4893,4894,4895],{},"kontekst aplikacji ",[459,4896,4897],{},"hibernate.current_session_context_class",[442,4899,4900,4901,4904],{},"automatyczne zamykanie transakcji ",[459,4902,4903],{},"hibernate.transaction.auto_close_session",", które upraszcza obsługę transakcji",[442,4906,4907,4908],{},"strategia zarządzania strukturą w bazie danych ",[459,4909,4910],{},"hibernate.hbm2ddl.auto",[426,4912,4913],{},"#Tworzenie pierwszej encji",[426,4915,4916],{},"W celu przetestowania poprawności konfiguracji stworzymy i zarejestrujemy prostą encję użytkownika naszej aplikacji. W tym celu stworzymy prostą klasę encji:",[452,4918,4920],{"className":598,"code":4919,"language":600,"meta":457,"style":457},"package pl.xperios.hibernatestarter.model;\n\nimport java.io.Serializable;\nimport javax.persistence.Entity;\nimport javax.persistence.GeneratedValue;\nimport javax.persistence.GenerationType;\nimport javax.persistence.Id;\n\n@Entity\npublic class UserData implements Serializable {\n\n    @Id\n    @GeneratedValue(strategy = GenerationType.AUTO)\n    Long userId;\n    String name;\n    String fullName;\n\n    public String getFullName() {\n        return fullName;\n    }\n\n    public void setFullName(String fullName) {\n        this.fullName = fullName;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public Long getUserId() {\n        return userId;\n    }\n\n    public void setUserId(Long userId) {\n        this.userId = userId;\n    }\n\n    @Override\n    public String toString() {\n        return \"UserData{\" + \"userId=\" + userId + \", name=\" + name + \", fullName=\" + fullName + '}';\n    }\n}\n",[459,4921,4922,4927,4931,4936,4941,4946,4951,4956,4960,4965,4970,4974,4979,4984,4989,4994,4999,5003,5008,5013,5017,5021,5026,5031,5035,5039,5044,5049,5053,5057,5062,5066,5070,5074,5079,5084,5088,5092,5097,5102,5106,5110,5114,5118,5123,5127],{"__ignoreMap":457},[462,4923,4924],{"class":464,"line":465},[462,4925,4926],{},"package pl.xperios.hibernatestarter.model;\n",[462,4928,4929],{"class":464,"line":471},[462,4930,475],{"emptyLinePlaceholder":474},[462,4932,4933],{"class":464,"line":478},[462,4934,4935],{},"import java.io.Serializable;\n",[462,4937,4938],{"class":464,"line":484},[462,4939,4940],{},"import javax.persistence.Entity;\n",[462,4942,4943],{"class":464,"line":489},[462,4944,4945],{},"import javax.persistence.GeneratedValue;\n",[462,4947,4948],{"class":464,"line":495},[462,4949,4950],{},"import javax.persistence.GenerationType;\n",[462,4952,4953],{"class":464,"line":501},[462,4954,4955],{},"import javax.persistence.Id;\n",[462,4957,4958],{"class":464,"line":506},[462,4959,475],{"emptyLinePlaceholder":474},[462,4961,4962],{"class":464,"line":512},[462,4963,4964],{},"@Entity\n",[462,4966,4967],{"class":464,"line":518},[462,4968,4969],{},"public class UserData implements Serializable {\n",[462,4971,4972],{"class":464,"line":524},[462,4973,475],{"emptyLinePlaceholder":474},[462,4975,4976],{"class":464,"line":530},[462,4977,4978],{},"    @Id\n",[462,4980,4981],{"class":464,"line":536},[462,4982,4983],{},"    @GeneratedValue(strategy = GenerationType.AUTO)\n",[462,4985,4986],{"class":464,"line":542},[462,4987,4988],{},"    Long userId;\n",[462,4990,4991],{"class":464,"line":547},[462,4992,4993],{},"    String name;\n",[462,4995,4996],{"class":464,"line":553},[462,4997,4998],{},"    String fullName;\n",[462,5000,5001],{"class":464,"line":558},[462,5002,475],{"emptyLinePlaceholder":474},[462,5004,5005],{"class":464,"line":564},[462,5006,5007],{},"    public String getFullName() {\n",[462,5009,5010],{"class":464,"line":693},[462,5011,5012],{},"        return fullName;\n",[462,5014,5015],{"class":464,"line":699},[462,5016,702],{},[462,5018,5019],{"class":464,"line":705},[462,5020,475],{"emptyLinePlaceholder":474},[462,5022,5023],{"class":464,"line":710},[462,5024,5025],{},"    public void setFullName(String fullName) {\n",[462,5027,5028],{"class":464,"line":715},[462,5029,5030],{},"        this.fullName = fullName;\n",[462,5032,5033],{"class":464,"line":721},[462,5034,702],{},[462,5036,5037],{"class":464,"line":727},[462,5038,475],{"emptyLinePlaceholder":474},[462,5040,5041],{"class":464,"line":732},[462,5042,5043],{},"    public String getName() {\n",[462,5045,5046],{"class":464,"line":738},[462,5047,5048],{},"        return name;\n",[462,5050,5051],{"class":464,"line":744},[462,5052,702],{},[462,5054,5055],{"class":464,"line":750},[462,5056,475],{"emptyLinePlaceholder":474},[462,5058,5059],{"class":464,"line":756},[462,5060,5061],{},"    public void setName(String name) {\n",[462,5063,5064],{"class":464,"line":762},[462,5065,1257],{},[462,5067,5068],{"class":464,"line":768},[462,5069,702],{},[462,5071,5072],{"class":464,"line":774},[462,5073,475],{"emptyLinePlaceholder":474},[462,5075,5076],{"class":464,"line":780},[462,5077,5078],{},"    public Long getUserId() {\n",[462,5080,5081],{"class":464,"line":786},[462,5082,5083],{},"        return userId;\n",[462,5085,5086],{"class":464,"line":791},[462,5087,702],{},[462,5089,5090],{"class":464,"line":797},[462,5091,475],{"emptyLinePlaceholder":474},[462,5093,5094],{"class":464,"line":803},[462,5095,5096],{},"    public void setUserId(Long userId) {\n",[462,5098,5099],{"class":464,"line":808},[462,5100,5101],{},"        this.userId = userId;\n",[462,5103,5104],{"class":464,"line":2107},[462,5105,702],{},[462,5107,5108],{"class":464,"line":2112},[462,5109,475],{"emptyLinePlaceholder":474},[462,5111,5112],{"class":464,"line":2117},[462,5113,1107],{},[462,5115,5116],{"class":464,"line":2431},[462,5117,1283],{},[462,5119,5120],{"class":464,"line":2437},[462,5121,5122],{},"        return \"UserData{\" + \"userId=\" + userId + \", name=\" + name + \", fullName=\" + fullName + '}';\n",[462,5124,5125],{"class":464,"line":2443},[462,5126,702],{},[462,5128,5129],{"class":464,"line":2448},[462,5130,811],{},[426,5132,5133,5134,5137],{},"Powyższa encja została oznaczona za pomocą anotacji ",[459,5135,5136],{},"@Entity",", dzięki czemu Hibernate będzie stworzononą klasę traktował jako encję.\nniektóre właściwości również posiadają anotacje i tak pole userId zostało opatrzone anotacją ID, które przekłada się na to że pole to traktowane jest jako klucz główny wraz ze strategią generowania identyfikatorów w sposób automatyczny.",[426,5139,5140,5141,5144],{},"Powyższą encję należy zarejestrować w pliku konfiguracyjnym Hibernate (",[459,5142,5143],{},"hibernate.cfg.xml","):",[452,5146,5148],{"className":454,"code":5147,"language":456,"meta":457,"style":457},"...\n    \u003Cproperty name=\"hibernate.transaction.auto_close_session\">true\u003C\u002Fproperty>\n    \u003Cmapping class=\"pl.xperios.hibernatestarter.model.UserData\"\u002F>\n  \u003C\u002Fsession-factory>\n...\n",[459,5149,5150,5155,5159,5164,5168],{"__ignoreMap":457},[462,5151,5152],{"class":464,"line":465},[462,5153,5154],{},"...\n",[462,5156,5157],{"class":464,"line":471},[462,5158,4837],{},[462,5160,5161],{"class":464,"line":478},[462,5162,5163],{},"    \u003Cmapping class=\"pl.xperios.hibernatestarter.model.UserData\"\u002F>\n",[462,5165,5166],{"class":464,"line":484},[462,5167,4842],{},[462,5169,5170],{"class":464,"line":489},[462,5171,5154],{},[426,5173,5174],{},"##Test",[426,5176,5177],{},"Mając wszystkie elementy tworzymy test, który doda parę rekordów do bazy a następnie pobierze je i wyświetli w konsoli:",[452,5179,5181],{"className":598,"code":5180,"language":600,"meta":457,"style":457},"package pl.xperios.hibernatestarter;\n\nimport java.util.List;\nimport junit.framework.Test;\nimport junit.framework.TestCase;\nimport junit.framework.TestSuite;\nimport org.hibernate.Transaction;\nimport org.hibernate.classic.Session;\nimport pl.xperios.hibernatestarter.HibernateUtil;\nimport pl.xperios.hibernatestarter.model.UserData;\n\npublic class AppTest extends TestCase {\n\n    public AppTest(String testName) {\n        super(testName);\n    }\n\n    public static Test suite() {\n        return new TestSuite(AppTest.class);\n    }\n\n    public void testApp() {\n\n        Session session = HibernateUtil.getSessionFactory().getCurrentSession();\n        Transaction transaction = session.beginTransaction();\n        UserData data = new UserData();\n        data.setFullName(\"FullName1\");\n        data.setName(\"Name1\");\n        session.save(data);\n        data = new UserData();\n        data.setFullName(\"FullName2\");\n        data.setName(\"Name3\");\n        session.save(data);\n        transaction.commit();\n\n\n        session = HibernateUtil.getSessionFactory().getCurrentSession();\n        transaction = session.beginTransaction();\n        List output = session.createCriteria(UserData.class).list();\n        System.out.println(\"Size: \" + output.size());\n        System.out.println(\"Size: \" + output);\n        transaction.commit();\n    }\n}\n",[459,5182,5183,5187,5191,5196,5201,5206,5211,5216,5221,5226,5231,5235,5240,5244,5249,5254,5258,5262,5267,5272,5276,5280,5285,5289,5294,5299,5304,5309,5314,5319,5324,5329,5334,5338,5343,5347,5351,5356,5361,5366,5371,5376,5380,5384],{"__ignoreMap":457},[462,5184,5185],{"class":464,"line":465},[462,5186,4667],{},[462,5188,5189],{"class":464,"line":471},[462,5190,475],{"emptyLinePlaceholder":474},[462,5192,5193],{"class":464,"line":478},[462,5194,5195],{},"import java.util.List;\n",[462,5197,5198],{"class":464,"line":484},[462,5199,5200],{},"import junit.framework.Test;\n",[462,5202,5203],{"class":464,"line":489},[462,5204,5205],{},"import junit.framework.TestCase;\n",[462,5207,5208],{"class":464,"line":495},[462,5209,5210],{},"import junit.framework.TestSuite;\n",[462,5212,5213],{"class":464,"line":501},[462,5214,5215],{},"import org.hibernate.Transaction;\n",[462,5217,5218],{"class":464,"line":506},[462,5219,5220],{},"import org.hibernate.classic.Session;\n",[462,5222,5223],{"class":464,"line":512},[462,5224,5225],{},"import pl.xperios.hibernatestarter.HibernateUtil;\n",[462,5227,5228],{"class":464,"line":518},[462,5229,5230],{},"import pl.xperios.hibernatestarter.model.UserData;\n",[462,5232,5233],{"class":464,"line":524},[462,5234,475],{"emptyLinePlaceholder":474},[462,5236,5237],{"class":464,"line":530},[462,5238,5239],{},"public class AppTest extends TestCase {\n",[462,5241,5242],{"class":464,"line":536},[462,5243,475],{"emptyLinePlaceholder":474},[462,5245,5246],{"class":464,"line":542},[462,5247,5248],{},"    public AppTest(String testName) {\n",[462,5250,5251],{"class":464,"line":547},[462,5252,5253],{},"        super(testName);\n",[462,5255,5256],{"class":464,"line":553},[462,5257,702],{},[462,5259,5260],{"class":464,"line":558},[462,5261,475],{"emptyLinePlaceholder":474},[462,5263,5264],{"class":464,"line":564},[462,5265,5266],{},"    public static Test suite() {\n",[462,5268,5269],{"class":464,"line":693},[462,5270,5271],{},"        return new TestSuite(AppTest.class);\n",[462,5273,5274],{"class":464,"line":699},[462,5275,702],{},[462,5277,5278],{"class":464,"line":705},[462,5279,475],{"emptyLinePlaceholder":474},[462,5281,5282],{"class":464,"line":710},[462,5283,5284],{},"    public void testApp() {\n",[462,5286,5287],{"class":464,"line":715},[462,5288,475],{"emptyLinePlaceholder":474},[462,5290,5291],{"class":464,"line":721},[462,5292,5293],{},"        Session session = HibernateUtil.getSessionFactory().getCurrentSession();\n",[462,5295,5296],{"class":464,"line":727},[462,5297,5298],{},"        Transaction transaction = session.beginTransaction();\n",[462,5300,5301],{"class":464,"line":732},[462,5302,5303],{},"        UserData data = new UserData();\n",[462,5305,5306],{"class":464,"line":738},[462,5307,5308],{},"        data.setFullName(\"FullName1\");\n",[462,5310,5311],{"class":464,"line":744},[462,5312,5313],{},"        data.setName(\"Name1\");\n",[462,5315,5316],{"class":464,"line":750},[462,5317,5318],{},"        session.save(data);\n",[462,5320,5321],{"class":464,"line":756},[462,5322,5323],{},"        data = new UserData();\n",[462,5325,5326],{"class":464,"line":762},[462,5327,5328],{},"        data.setFullName(\"FullName2\");\n",[462,5330,5331],{"class":464,"line":768},[462,5332,5333],{},"        data.setName(\"Name3\");\n",[462,5335,5336],{"class":464,"line":774},[462,5337,5318],{},[462,5339,5340],{"class":464,"line":780},[462,5341,5342],{},"        transaction.commit();\n",[462,5344,5345],{"class":464,"line":786},[462,5346,475],{"emptyLinePlaceholder":474},[462,5348,5349],{"class":464,"line":791},[462,5350,475],{"emptyLinePlaceholder":474},[462,5352,5353],{"class":464,"line":797},[462,5354,5355],{},"        session = HibernateUtil.getSessionFactory().getCurrentSession();\n",[462,5357,5358],{"class":464,"line":803},[462,5359,5360],{},"        transaction = session.beginTransaction();\n",[462,5362,5363],{"class":464,"line":808},[462,5364,5365],{},"        List output = session.createCriteria(UserData.class).list();\n",[462,5367,5368],{"class":464,"line":2107},[462,5369,5370],{},"        System.out.println(\"Size: \" + output.size());\n",[462,5372,5373],{"class":464,"line":2112},[462,5374,5375],{},"        System.out.println(\"Size: \" + output);\n",[462,5377,5378],{"class":464,"line":2117},[462,5379,5342],{},[462,5381,5382],{"class":464,"line":2431},[462,5383,702],{},[462,5385,5386],{"class":464,"line":2437},[462,5387,811],{},[426,5389,5390],{},"W konsoli powinno zostać wyświetlony następujący wynik:",[452,5392,5394],{"className":3729,"code":5393,"language":3731,"meta":457,"style":457},"Hibernate: insert into UserData (fullName, name, userId) values (?, ?, ?)\nHibernate: insert into UserData (fullName, name, userId) values (?, ?, ?)\nHibernate: select this_.userId as userId0_0_, this_.fullName as fullName0_0_, this_.name as name0_0_ from UserData this_\nSize: 2\nSize: [UserData{userId=1, name=Name1, fullName=FullName1}, UserData{userId=2, name=Name3, fullName=FullName2}]\n",[459,5395,5396,5436,5466,5506,5515],{"__ignoreMap":457},[462,5397,5398,5401,5404,5407,5410,5413,5416,5419,5422,5425,5427,5429,5431,5433],{"class":464,"line":465},[462,5399,5400],{"class":3738},"Hibernate:",[462,5402,5403],{"class":3742}," insert",[462,5405,5406],{"class":3742}," into",[462,5408,5409],{"class":3742}," UserData",[462,5411,5412],{"class":4186}," (fullName, ",[462,5414,5415],{"class":3742},"name,",[462,5417,5418],{"class":3742}," userId",[462,5420,5421],{"class":4186},") values (",[462,5423,5424],{"class":4190},"?",[462,5426,2744],{"class":4186},[462,5428,5424],{"class":4190},[462,5430,2744],{"class":4186},[462,5432,5424],{"class":4190},[462,5434,5435],{"class":4186},")\n",[462,5437,5438,5440,5442,5444,5446,5448,5450,5452,5454,5456,5458,5460,5462,5464],{"class":464,"line":471},[462,5439,5400],{"class":3738},[462,5441,5403],{"class":3742},[462,5443,5406],{"class":3742},[462,5445,5409],{"class":3742},[462,5447,5412],{"class":4186},[462,5449,5415],{"class":3742},[462,5451,5418],{"class":3742},[462,5453,5421],{"class":4186},[462,5455,5424],{"class":4190},[462,5457,2744],{"class":4186},[462,5459,5424],{"class":4190},[462,5461,2744],{"class":4186},[462,5463,5424],{"class":4190},[462,5465,5435],{"class":4186},[462,5467,5468,5470,5473,5476,5479,5482,5485,5487,5490,5493,5495,5498,5501,5503],{"class":464,"line":478},[462,5469,5400],{"class":3738},[462,5471,5472],{"class":3742}," select",[462,5474,5475],{"class":3742}," this_.userId",[462,5477,5478],{"class":3742}," as",[462,5480,5481],{"class":3742}," userId0_0_,",[462,5483,5484],{"class":3742}," this_.fullName",[462,5486,5478],{"class":3742},[462,5488,5489],{"class":3742}," fullName0_0_,",[462,5491,5492],{"class":3742}," this_.name",[462,5494,5478],{"class":3742},[462,5496,5497],{"class":3742}," name0_0_",[462,5499,5500],{"class":3742}," from",[462,5502,5409],{"class":3742},[462,5504,5505],{"class":3742}," this_\n",[462,5507,5508,5511],{"class":464,"line":484},[462,5509,5510],{"class":3738},"Size:",[462,5512,5514],{"class":5513},"sbssI"," 2\n",[462,5516,5517,5519,5522,5524,5527,5530,5532,5535,5538,5540,5543,5546,5548,5551,5553,5555,5558,5560,5562,5565],{"class":464,"line":489},[462,5518,5510],{"class":3738},[462,5520,5521],{"class":4186}," [UserData{userId",[462,5523,4191],{"class":4190},[462,5525,5526],{"class":3742},"1,",[462,5528,5529],{"class":4186}," name",[462,5531,4191],{"class":4190},[462,5533,5534],{"class":3742},"Name1,",[462,5536,5537],{"class":4186}," fullName",[462,5539,4191],{"class":4190},[462,5541,5542],{"class":3742},"FullName1",[462,5544,5545],{"class":4186},"}, UserData{userId",[462,5547,4191],{"class":4190},[462,5549,5550],{"class":3742},"2,",[462,5552,5529],{"class":4186},[462,5554,4191],{"class":4190},[462,5556,5557],{"class":3742},"Name3,",[462,5559,5537],{"class":4186},[462,5561,4191],{"class":4190},[462,5563,5564],{"class":3742},"FullName2",[462,5566,5567],{"class":4186},"}]\n",[984,5569,5570],{},"html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}",{"title":457,"searchDepth":471,"depth":471,"links":5572},[],"2012-02-02","Prezentacja Hibernate jako narzędzia do utrwalania danych",{"layout":993},"\u002Fblog\u002F2012-02-02-fast-track-to-hibernate",{"title":4158,"description":5574},"2.blog\u002F2012-02-02-fast-track-to-hibernate","ymeVyItqF8QaFR8WBBRnEXTxSEngvHuDW5_9K1bsDxY",{"id":5581,"title":5582,"authors":409,"badge":409,"body":5583,"date":5658,"description":5659,"extension":991,"image":409,"meta":5660,"navigation":474,"path":5661,"seo":5662,"stem":5663,"__hash__":5664},"posts\u002F2.blog\u002F2012-02-04-update-web-xml-for-netbeans-workflow.md","Aktualizacja web.xml dla Netbeans",{"type":423,"value":5584,"toc":5656},[5585,5588,5598,5618,5621,5651,5654],[426,5586,5587],{},"Tworząc nowy projekt czy to za pomocą kreatora dołączonego do IDE czy za pomocą archetypu Maven zdarza się, że utworzona wersja deskryptora wdrożenia jest dość nieaktualna.\nPracując z Netbeans chcąc dodać nowy servlet jeżeli deskryptor będzie w wersji 2.3 bądź starszej, zostaniemy poinformowani komunikatem, że nie jest to możliwe:",[426,5589,5590,5593,5594,5597],{},[3284,5591],{"alt":457,"src":5592},"\u002Fposts\u002Fassets\u002Fnetbeans-web-xml-update.jpg","\nW tym celu należy w pliku ",[459,5595,5596],{},"web.xml"," skasować dotychczasowy schemat walidacji DTD:",[452,5599,5601],{"className":454,"code":5600,"language":456,"meta":457,"style":457},"\u003C!DOCTYPE web-app\n   PUBLIC \"-\u002F\u002FSun Microsystems, Inc.\u002F\u002FDTD Web Application 2.3\u002F\u002FEN\"\n   \"http:\u002F\u002Fjava.sun.com\u002Fdtd\u002Fweb-app_2_3.dtd\">\n",[459,5602,5603,5608,5613],{"__ignoreMap":457},[462,5604,5605],{"class":464,"line":465},[462,5606,5607],{},"\u003C!DOCTYPE web-app\n",[462,5609,5610],{"class":464,"line":471},[462,5611,5612],{},"   PUBLIC \"-\u002F\u002FSun Microsystems, Inc.\u002F\u002FDTD Web Application 2.3\u002F\u002FEN\"\n",[462,5614,5615],{"class":464,"line":478},[462,5616,5617],{},"   \"http:\u002F\u002Fjava.sun.com\u002Fdtd\u002Fweb-app_2_3.dtd\">\n",[426,5619,5620],{},"a następnie dodać nowy schemat walidacji XSD w głównym elemencie pliku xml:",[452,5622,5624],{"className":454,"code":5623,"language":456,"meta":457,"style":457},"\u003Cweb-app xmlns:xsi=\"http:\u002F\u002Fwww.w3.org\u002F2001\u002FXMLSchema-instance\"\n        xmlns=\"http:\u002F\u002Fjava.sun.com\u002Fxml\u002Fns\u002Fjavaee\"\n        xmlns:web=\"http:\u002F\u002Fjava.sun.com\u002Fxml\u002Fns\u002Fj2ee\u002Fweb-app_2_4.xsd\"\n        xsi:schemaLocation=\"http:\u002F\u002Fjava.sun.com\u002Fxml\u002Fns\u002Fj2ee http:\u002F\u002Fjava.sun.com\u002Fxml\u002Fns\u002Fj2ee\u002Fweb-app_2_4.xsd\"\n        version=\"2.4\">\n",[459,5625,5626,5631,5636,5641,5646],{"__ignoreMap":457},[462,5627,5628],{"class":464,"line":465},[462,5629,5630],{},"\u003Cweb-app xmlns:xsi=\"http:\u002F\u002Fwww.w3.org\u002F2001\u002FXMLSchema-instance\"\n",[462,5632,5633],{"class":464,"line":471},[462,5634,5635],{},"        xmlns=\"http:\u002F\u002Fjava.sun.com\u002Fxml\u002Fns\u002Fjavaee\"\n",[462,5637,5638],{"class":464,"line":478},[462,5639,5640],{},"        xmlns:web=\"http:\u002F\u002Fjava.sun.com\u002Fxml\u002Fns\u002Fj2ee\u002Fweb-app_2_4.xsd\"\n",[462,5642,5643],{"class":464,"line":484},[462,5644,5645],{},"        xsi:schemaLocation=\"http:\u002F\u002Fjava.sun.com\u002Fxml\u002Fns\u002Fj2ee http:\u002F\u002Fjava.sun.com\u002Fxml\u002Fns\u002Fj2ee\u002Fweb-app_2_4.xsd\"\n",[462,5647,5648],{"class":464,"line":489},[462,5649,5650],{},"        version=\"2.4\">\n",[426,5652,5653],{},"Od tej pory można bez przeszkód dodawać servlety przez wspomniany kreator.",[984,5655,986],{},{"title":457,"searchDepth":471,"depth":471,"links":5657},[],"2012-02-04","Wprowadzenie zmian w deskrypotrze wdrożenia w celu wyeliminowania błędów w Netbeans",{"layout":993},"\u002Fblog\u002F2012-02-04-update-web-xml-for-netbeans-workflow",{"title":5582,"description":5659},"2.blog\u002F2012-02-04-update-web-xml-for-netbeans-workflow","JWFZIglTOKlKedGQAP7nM7u2UOwhUWvY4r5WEHJvo_o",{"id":5666,"title":5667,"authors":409,"badge":409,"body":5668,"date":5994,"description":5995,"extension":991,"image":409,"meta":5996,"navigation":474,"path":5997,"seo":5998,"stem":5999,"__hash__":6000},"posts\u002F2.blog\u002F2012-02-05-gxt-templates-for-netbeans.md","Szablony w Netbeans",{"type":423,"value":5669,"toc":5992},[5670,5673,5835,5846,5892,5895,5927,5930,5976,5979,5990],[426,5671,5672],{},"Podczas pracy z różnymi bibliotekami bywa, że pewne czynności są powtarzane nader często. Popularne biblioteki posiadają rozszerzenia, bądź natywne wsparcie ze strony IDE jak np. kreatory.\nNiestety nie wszystkie biblioteki posiadają tak ogromne wsparcie jak choćby Spring czy Hibernate, co nie oznacza że są gorsze.\nProgramista jako użytkownik danej biblioteki pomimo braku wsparcia może jednak sam opracować pewne wzorce, które powtarzają się w trakcie pracy i je zautomatyzować poprzez makra czy też szablony. W dzisiejszym wpisie poświęcimy trochę czasu aby zautomatyzować tworzenie getterów i setterów dla modelu wykorzystywanego przez GXT.\nStruktura modelu GXT wygląda nieco inaczej niż zwykłe POJO:",[452,5674,5676],{"className":598,"code":5675,"language":600,"meta":457,"style":457},"package pl.bnsit.rssreader.shared;\n\nimport com.extjs.gxt.ui.client.data.BeanModel;\n\npublic class ExampleModelModel extends BeanModel{\n    \n    public static final String _NAME = \"name\";\n    public static final String _URL = \"url\";\n    public static final String _PROMOTED = \"promoted\";\n    \n    public String getName() {\n        return get(_NAME);\n    }\n\n    public void setName(String name) {\n        set(_NAME, name);\n    }\n\n    public String getUrl() {\n        return get(_URL);\n    }\n\n    public void setUrl(String url) {\n        set(_URL, url);\n    }\n\n    public Boolean getPromoted() {\n        return get(_PROMOTED);\n    }\n\n    public void setPromoted(Boolean promoted) {\n        set(_PROMOTED, promoted);\n    }\n    \n}\n",[459,5677,5678,5683,5687,5692,5696,5701,5706,5711,5716,5721,5725,5729,5734,5738,5742,5746,5751,5755,5759,5764,5769,5773,5777,5782,5787,5791,5795,5800,5805,5809,5813,5818,5823,5827,5831],{"__ignoreMap":457},[462,5679,5680],{"class":464,"line":465},[462,5681,5682],{},"package pl.bnsit.rssreader.shared;\n",[462,5684,5685],{"class":464,"line":471},[462,5686,475],{"emptyLinePlaceholder":474},[462,5688,5689],{"class":464,"line":478},[462,5690,5691],{},"import com.extjs.gxt.ui.client.data.BeanModel;\n",[462,5693,5694],{"class":464,"line":484},[462,5695,475],{"emptyLinePlaceholder":474},[462,5697,5698],{"class":464,"line":489},[462,5699,5700],{},"public class ExampleModelModel extends BeanModel{\n",[462,5702,5703],{"class":464,"line":495},[462,5704,5705],{},"    \n",[462,5707,5708],{"class":464,"line":501},[462,5709,5710],{},"    public static final String _NAME = \"name\";\n",[462,5712,5713],{"class":464,"line":506},[462,5714,5715],{},"    public static final String _URL = \"url\";\n",[462,5717,5718],{"class":464,"line":512},[462,5719,5720],{},"    public static final String _PROMOTED = \"promoted\";\n",[462,5722,5723],{"class":464,"line":518},[462,5724,5705],{},[462,5726,5727],{"class":464,"line":524},[462,5728,5043],{},[462,5730,5731],{"class":464,"line":530},[462,5732,5733],{},"        return get(_NAME);\n",[462,5735,5736],{"class":464,"line":536},[462,5737,702],{},[462,5739,5740],{"class":464,"line":542},[462,5741,475],{"emptyLinePlaceholder":474},[462,5743,5744],{"class":464,"line":547},[462,5745,5061],{},[462,5747,5748],{"class":464,"line":553},[462,5749,5750],{},"        set(_NAME, name);\n",[462,5752,5753],{"class":464,"line":558},[462,5754,702],{},[462,5756,5757],{"class":464,"line":564},[462,5758,475],{"emptyLinePlaceholder":474},[462,5760,5761],{"class":464,"line":693},[462,5762,5763],{},"    public String getUrl() {\n",[462,5765,5766],{"class":464,"line":699},[462,5767,5768],{},"        return get(_URL);\n",[462,5770,5771],{"class":464,"line":705},[462,5772,702],{},[462,5774,5775],{"class":464,"line":710},[462,5776,475],{"emptyLinePlaceholder":474},[462,5778,5779],{"class":464,"line":715},[462,5780,5781],{},"    public void setUrl(String url) {\n",[462,5783,5784],{"class":464,"line":721},[462,5785,5786],{},"        set(_URL, url);\n",[462,5788,5789],{"class":464,"line":727},[462,5790,702],{},[462,5792,5793],{"class":464,"line":732},[462,5794,475],{"emptyLinePlaceholder":474},[462,5796,5797],{"class":464,"line":738},[462,5798,5799],{},"    public Boolean getPromoted() {\n",[462,5801,5802],{"class":464,"line":744},[462,5803,5804],{},"        return get(_PROMOTED);\n",[462,5806,5807],{"class":464,"line":750},[462,5808,702],{},[462,5810,5811],{"class":464,"line":756},[462,5812,475],{"emptyLinePlaceholder":474},[462,5814,5815],{"class":464,"line":762},[462,5816,5817],{},"    public void setPromoted(Boolean promoted) {\n",[462,5819,5820],{"class":464,"line":768},[462,5821,5822],{},"        set(_PROMOTED, promoted);\n",[462,5824,5825],{"class":464,"line":774},[462,5826,702],{},[462,5828,5829],{"class":464,"line":780},[462,5830,5705],{},[462,5832,5833],{"class":464,"line":786},[462,5834,811],{},[426,5836,5837,5838,5841,5842,5845],{},"Jak widać model ten posiada gettery i settery, ale różniące się sposobem przetrzymywania zmiennych. aby stworzyć powyższy plik ręcznie zajęłoby to programiście sporo czasu a przecież o to w pracy nie chodzi.\nZ pomocą przychodzą nam szablony, dzięki którym za pomocą pewnej sekwencji znaków można wygenerować szablon, w którym należy uzupełnić elementy, które wyróżniają dany blok kodu.\nSzablon stworzymy dla popularnego IDE – Netbeans, który posiada edytor szablonów w ",[459,5839,5840],{},"Tools->Options->Editor->Code Templates",".\nUtwórzmy nowy szablon, który wywołamy za pomocą sekwencji ",[459,5843,5844],{},"gs"," i następującej treści:",[452,5847,5849],{"className":598,"code":5848,"language":600,"meta":457,"style":457},"    public static final String _Property = \"property_id\";\n    \n    public String getProperty() {\n        return get(_Property);\n    }\n\n    public void setProperty(String property_id) {\n        set(_Property, property_id);\n    }\n",[459,5850,5851,5856,5860,5865,5870,5874,5878,5883,5888],{"__ignoreMap":457},[462,5852,5853],{"class":464,"line":465},[462,5854,5855],{},"    public static final String _Property = \"property_id\";\n",[462,5857,5858],{"class":464,"line":471},[462,5859,5705],{},[462,5861,5862],{"class":464,"line":478},[462,5863,5864],{},"    public String getProperty() {\n",[462,5866,5867],{"class":464,"line":484},[462,5868,5869],{},"        return get(_Property);\n",[462,5871,5872],{"class":464,"line":489},[462,5873,702],{},[462,5875,5876],{"class":464,"line":495},[462,5877,475],{"emptyLinePlaceholder":474},[462,5879,5880],{"class":464,"line":501},[462,5881,5882],{},"    public void setProperty(String property_id) {\n",[462,5884,5885],{"class":464,"line":506},[462,5886,5887],{},"        set(_Property, property_id);\n",[462,5889,5890],{"class":464,"line":512},[462,5891,702],{},[426,5893,5894],{},"Po zapisaniu można przetestować działanie wpisując w edytorze klasy gs a następnie wcisnąć klawisz TAB – tekst zapisany automatycznie się generuje. Nie jest to jednak zadowalający nas rezultat ponieważ pomimo wygenerowanego tekstu nazwy oraz typy należy poprawić. Aby mieć wpływ na elementy szablonu należy przedstawić elementy rozszerzające szablony:",[439,5896,5897,5903,5909,5915,5921],{},[442,5898,5899,5902],{},[459,5900,5901],{},"${cursor}"," – definiuje pozycję karetki kursora po wygenerowaniu kodu,",[442,5904,5905,5908],{},[459,5906,5907],{},"${selection}"," – definuje pozycję wklejenia tekstu, który został zaznaczony; użycie tego znacznika spowoduje pojawianie się tego szablonu jedynie po zaznaczeniu pewnego fragmentu tekstu,",[442,5910,5911,5914],{},[459,5912,5913],{},"${ELEM newVarName default=”Property”}"," – definiuje nową zmienną ELEM o domyślnej wartości Property",[442,5916,5917,5920],{},[459,5918,5919],{},"${DEFTYPE leftSideType default=”Object”}"," – definiuje nowy zwracany typ danych w zmiennej DEFTYPE o domyślnej klasie Object",[442,5922,5923,5926],{},[459,5924,5925],{},"${INITTYPE rightSideType default=”Object”}"," – definiuje nowy inicjalizowany typ danych w zmiennej INITTYPE o domyślnej klasie Object\nPowyższe zmienne to tylko dobry początek do tego aby zapoznać się z szerszą gamą typów, które można wykorzystywać w szablonach a w przypadku Netbeans-a jest to wspaniała kolekcja, która pozwala na tworzenie genialnych szablonów.",[426,5928,5929],{},"Ostatecznie dynamiczny szablon ma postać:",[452,5931,5933],{"className":598,"code":5932,"language":600,"meta":457,"style":457},"    public static final String _${ELEM newVarName default=\"Property\"} = \"${ID newVarName default=\"id\"}\";\n    \n    public ${TYPE lefttSideType default=\"Object\"} get${ELEM}() {\n        return get(_${ELEM});\n    }\n\n    public void set${ELEM}(${TYPE} _input) {\n        set(_${ELEM}, _input);\n    }\n",[459,5934,5935,5940,5944,5949,5954,5958,5962,5967,5972],{"__ignoreMap":457},[462,5936,5937],{"class":464,"line":465},[462,5938,5939],{},"    public static final String _${ELEM newVarName default=\"Property\"} = \"${ID newVarName default=\"id\"}\";\n",[462,5941,5942],{"class":464,"line":471},[462,5943,5705],{},[462,5945,5946],{"class":464,"line":478},[462,5947,5948],{},"    public ${TYPE lefttSideType default=\"Object\"} get${ELEM}() {\n",[462,5950,5951],{"class":464,"line":484},[462,5952,5953],{},"        return get(_${ELEM});\n",[462,5955,5956],{"class":464,"line":489},[462,5957,702],{},[462,5959,5960],{"class":464,"line":495},[462,5961,475],{"emptyLinePlaceholder":474},[462,5963,5964],{"class":464,"line":501},[462,5965,5966],{},"    public void set${ELEM}(${TYPE} _input) {\n",[462,5968,5969],{"class":464,"line":506},[462,5970,5971],{},"        set(_${ELEM}, _input);\n",[462,5973,5974],{"class":464,"line":512},[462,5975,702],{},[426,5977,5978],{},"Szablon wymaga do uzupełnienia:",[439,5980,5981,5984,5987],{},[442,5982,5983],{},"nazwy pseudo pola,",[442,5985,5986],{},"identyfiakatora pola,",[442,5988,5989],{},"typu pola, po których można się przełączać za pomocą klawisza TAB.",[984,5991,986],{},{"title":457,"searchDepth":471,"depth":471,"links":5993},[],"2012-02-05","Prezentacja możliwości szablonów w Netbeans na przykładzie tworzenia modyfikatorów dla GXT",{"layout":993},"\u002Fblog\u002F2012-02-05-gxt-templates-for-netbeans",{"title":5667,"description":5995},"2.blog\u002F2012-02-05-gxt-templates-for-netbeans","gjjR-fubKvigKYkd4ne-rM_hCeG6i8wThLJM86yd30g",{"id":6002,"title":6003,"authors":409,"badge":409,"body":6004,"date":6295,"description":6296,"extension":991,"image":409,"meta":6297,"navigation":474,"path":6298,"seo":6299,"stem":6300,"__hash__":6301},"posts\u002F2.blog\u002F2012-02-07-deploy-artifacts-to-the-repository.md","Instalacja artefaktu w zdalnym repozytorium Mavena",{"type":423,"value":6005,"toc":6293},[6006,6009,6108,6115,6219,6222,6277,6290],[426,6007,6008],{},"W jednym z poprzednich wpisów pokazaliśmy jak zdeployować stworzoną zależność po skompilowaniu projektu. Dzisiejszy wpis poświęcony jest umieszczaniu zależności w repozytorium przy pomocy linii komend.\nPomimo najszczerszych chęci wykonanie tego zadania zupełnie z linii komend jest niemożliwe. Należy stworzyć pom.xml o następującej treści:",[452,6010,6012],{"className":454,"code":6011,"language":456,"meta":457,"style":457},"\u003Cproject xmlns=\"http:\u002F\u002Fmaven.apache.org\u002FPOM\u002F4.0.0\" xmlns:xsi=\"http:\u002F\u002Fwww.w3.org\u002F2001\u002FXMLSchema-instance\"\n     xsi:schemaLocation=\"http:\u002F\u002Fmaven.apache.org\u002FPOM\u002F4.0.0 http:\u002F\u002Fmaven.apache.org\u002Fmaven-v4_0_0.xsd\">\n   \u003CmodelVersion>4.0.0\u003C\u002FmodelVersion>\n   \u003CgroupId>com.example\u003C\u002FgroupId>\n   \u003CartifactId>webdav-deploy-pom\u003C\u002FartifactId>\n   \u003Cpackaging>pom\u003C\u002Fpackaging>\n   \u003Cversion>1\u003C\u002Fversion>\n   \u003Cname>Deploy\u003C\u002Fname>\n   \u003Cbuild>\n      \u003Cextensions>\n         \u003Cextension>\n            \u003CgroupId>org.apache.maven.wagon\u003C\u002FgroupId>\n            \u003CartifactId>wagon-webdav\u003C\u002FartifactId>\n            \u003Cversion>1.0-beta-2\u003C\u002Fversion>\n         \u003C\u002Fextension>\n      \u003C\u002Fextensions>\n   \u003C\u002Fbuild>\n \n\u003C\u002Fproject>\n",[459,6013,6014,6019,6024,6029,6034,6039,6044,6049,6054,6059,6064,6069,6074,6079,6084,6089,6094,6099,6104],{"__ignoreMap":457},[462,6015,6016],{"class":464,"line":465},[462,6017,6018],{},"\u003Cproject xmlns=\"http:\u002F\u002Fmaven.apache.org\u002FPOM\u002F4.0.0\" xmlns:xsi=\"http:\u002F\u002Fwww.w3.org\u002F2001\u002FXMLSchema-instance\"\n",[462,6020,6021],{"class":464,"line":471},[462,6022,6023],{},"     xsi:schemaLocation=\"http:\u002F\u002Fmaven.apache.org\u002FPOM\u002F4.0.0 http:\u002F\u002Fmaven.apache.org\u002Fmaven-v4_0_0.xsd\">\n",[462,6025,6026],{"class":464,"line":478},[462,6027,6028],{},"   \u003CmodelVersion>4.0.0\u003C\u002FmodelVersion>\n",[462,6030,6031],{"class":464,"line":484},[462,6032,6033],{},"   \u003CgroupId>com.example\u003C\u002FgroupId>\n",[462,6035,6036],{"class":464,"line":489},[462,6037,6038],{},"   \u003CartifactId>webdav-deploy-pom\u003C\u002FartifactId>\n",[462,6040,6041],{"class":464,"line":495},[462,6042,6043],{},"   \u003Cpackaging>pom\u003C\u002Fpackaging>\n",[462,6045,6046],{"class":464,"line":501},[462,6047,6048],{},"   \u003Cversion>1\u003C\u002Fversion>\n",[462,6050,6051],{"class":464,"line":506},[462,6052,6053],{},"   \u003Cname>Deploy\u003C\u002Fname>\n",[462,6055,6056],{"class":464,"line":512},[462,6057,6058],{},"   \u003Cbuild>\n",[462,6060,6061],{"class":464,"line":518},[462,6062,6063],{},"      \u003Cextensions>\n",[462,6065,6066],{"class":464,"line":524},[462,6067,6068],{},"         \u003Cextension>\n",[462,6070,6071],{"class":464,"line":530},[462,6072,6073],{},"            \u003CgroupId>org.apache.maven.wagon\u003C\u002FgroupId>\n",[462,6075,6076],{"class":464,"line":536},[462,6077,6078],{},"            \u003CartifactId>wagon-webdav\u003C\u002FartifactId>\n",[462,6080,6081],{"class":464,"line":542},[462,6082,6083],{},"            \u003Cversion>1.0-beta-2\u003C\u002Fversion>\n",[462,6085,6086],{"class":464,"line":547},[462,6087,6088],{},"         \u003C\u002Fextension>\n",[462,6090,6091],{"class":464,"line":553},[462,6092,6093],{},"      \u003C\u002Fextensions>\n",[462,6095,6096],{"class":464,"line":558},[462,6097,6098],{},"   \u003C\u002Fbuild>\n",[462,6100,6101],{"class":464,"line":564},[462,6102,6103],{}," \n",[462,6105,6106],{"class":464,"line":693},[462,6107,3249],{},[426,6109,6110,6111,6114],{},"Będzie on dodawał obsługę pluginu służącego do wysyłania zależności na zdalny zasób.\nW pliku ",[459,6112,6113],{},"settings.xml",", który znajduje się w domyślnym folderze repozytorium .m2 należy dodać wpis, który pozwoli na autentyfikację do repozytorium, na którym będzie umieszczana zależność:",[452,6116,6118],{"className":454,"code":6117,"language":456,"meta":457,"style":457},"\u003Csettings \n   xmlns=\"http:\u002F\u002Fmaven.apache.org\u002FSETTINGS\u002F1.0.0\"\n   xmlns:xsi=\"http:\u002F\u002Fwww.w3.org\u002F2001\u002FXMLSchema-instance\" \n   xsi:schemaLocation=\"http:\u002F\u002Fmaven.apache.org\u002FSETTINGS\u002F1.0.0 http:\u002F\u002Fmaven.apache.org\u002Fxsd\u002Fsettings-1.0.0.xsd\">\n    \u003Cservers>\n        \u003Cserver>\n            \u003Cid>xperios\u003C\u002Fid>\n            \u003Cusername>your-google-id\u003C\u002Fusername>\n            \u003Cpassword>your-google-password\u003C\u002Fpassword>\n            \u003CfilePermissions>775\u003C\u002FfilePermissions>\n            \u003CdirectoryPermissions>775\u003C\u002FdirectoryPermissions>\n        \u003C\u002Fserver>\n        \u003Cserver>\n            \u003Cid>xperios-snapshot\u003C\u002Fid>\n            \u003Cusername>your-google-id\u003C\u002Fusername>\n            \u003Cpassword>your-google-password\u003C\u002Fpassword>\n            \u003CfilePermissions>775\u003C\u002FfilePermissions>\n            \u003CdirectoryPermissions>775\u003C\u002FdirectoryPermissions>\n        \u003C\u002Fserver>\n    \u003C\u002Fservers>\n\u003C\u002Fsettings>\n",[459,6119,6120,6125,6130,6135,6140,6145,6150,6155,6160,6165,6170,6175,6180,6184,6189,6193,6197,6201,6205,6209,6214],{"__ignoreMap":457},[462,6121,6122],{"class":464,"line":465},[462,6123,6124],{},"\u003Csettings \n",[462,6126,6127],{"class":464,"line":471},[462,6128,6129],{},"   xmlns=\"http:\u002F\u002Fmaven.apache.org\u002FSETTINGS\u002F1.0.0\"\n",[462,6131,6132],{"class":464,"line":478},[462,6133,6134],{},"   xmlns:xsi=\"http:\u002F\u002Fwww.w3.org\u002F2001\u002FXMLSchema-instance\" \n",[462,6136,6137],{"class":464,"line":484},[462,6138,6139],{},"   xsi:schemaLocation=\"http:\u002F\u002Fmaven.apache.org\u002FSETTINGS\u002F1.0.0 http:\u002F\u002Fmaven.apache.org\u002Fxsd\u002Fsettings-1.0.0.xsd\">\n",[462,6141,6142],{"class":464,"line":489},[462,6143,6144],{},"    \u003Cservers>\n",[462,6146,6147],{"class":464,"line":495},[462,6148,6149],{},"        \u003Cserver>\n",[462,6151,6152],{"class":464,"line":501},[462,6153,6154],{},"            \u003Cid>xperios\u003C\u002Fid>\n",[462,6156,6157],{"class":464,"line":506},[462,6158,6159],{},"            \u003Cusername>your-google-id\u003C\u002Fusername>\n",[462,6161,6162],{"class":464,"line":512},[462,6163,6164],{},"            \u003Cpassword>your-google-password\u003C\u002Fpassword>\n",[462,6166,6167],{"class":464,"line":518},[462,6168,6169],{},"            \u003CfilePermissions>775\u003C\u002FfilePermissions>\n",[462,6171,6172],{"class":464,"line":524},[462,6173,6174],{},"            \u003CdirectoryPermissions>775\u003C\u002FdirectoryPermissions>\n",[462,6176,6177],{"class":464,"line":530},[462,6178,6179],{},"        \u003C\u002Fserver>\n",[462,6181,6182],{"class":464,"line":536},[462,6183,6149],{},[462,6185,6186],{"class":464,"line":542},[462,6187,6188],{},"            \u003Cid>xperios-snapshot\u003C\u002Fid>\n",[462,6190,6191],{"class":464,"line":547},[462,6192,6159],{},[462,6194,6195],{"class":464,"line":553},[462,6196,6164],{},[462,6198,6199],{"class":464,"line":558},[462,6200,6169],{},[462,6202,6203],{"class":464,"line":564},[462,6204,6174],{},[462,6206,6207],{"class":464,"line":693},[462,6208,6179],{},[462,6210,6211],{"class":464,"line":699},[462,6212,6213],{},"    \u003C\u002Fservers>\n",[462,6215,6216],{"class":464,"line":705},[462,6217,6218],{},"\u003C\u002Fsettings>\n",[426,6220,6221],{},"Od tego momentu z folderu gdzie znajduje się zasób można wykonać polecenie:",[452,6223,6225],{"className":3729,"code":6224,"language":3731,"meta":457,"style":457},"mvn deploy:deploy-file \\\n-Durl=dav:https:\u002F\u002Fxperios.googlecode.com\u002Fsvn\u002Fmaven-repo\\\n-DrepositoryId=xperios-maven-repository \\\n-DgroupId=pl.xperios \\\n-DartifactId=sample-project \\\n-Dpackaging=jar \\\n-Dfile=xperios-sample-project.jar \\\n-Dversion=1.0 \\\n-DgeneratePom=true\n",[459,6226,6227,6237,6242,6247,6252,6257,6262,6267,6272],{"__ignoreMap":457},[462,6228,6229,6231,6234],{"class":464,"line":465},[462,6230,3992],{"class":3738},[462,6232,6233],{"class":3742}," deploy:deploy-file",[462,6235,6236],{"class":4186}," \\\n",[462,6238,6239],{"class":464,"line":471},[462,6240,6241],{"class":4186},"-Durl=dav:https:\u002F\u002Fxperios.googlecode.com\u002Fsvn\u002Fmaven-repo\\\n",[462,6243,6244],{"class":464,"line":478},[462,6245,6246],{"class":4186},"-DrepositoryId=xperios-maven-repository \\\n",[462,6248,6249],{"class":464,"line":484},[462,6250,6251],{"class":4186},"-DgroupId=pl.xperios \\\n",[462,6253,6254],{"class":464,"line":489},[462,6255,6256],{"class":4186},"-DartifactId=sample-project \\\n",[462,6258,6259],{"class":464,"line":495},[462,6260,6261],{"class":4186},"-Dpackaging=jar \\\n",[462,6263,6264],{"class":464,"line":501},[462,6265,6266],{"class":4186},"-Dfile=xperios-sample-project.jar \\\n",[462,6268,6269],{"class":464,"line":506},[462,6270,6271],{"class":4186},"-Dversion=1.0 \\\n",[462,6273,6274],{"class":464,"line":512},[462,6275,6276],{"class":4186},"-DgeneratePom=true\n",[426,6278,6279,6280,6283,6284,6287,6288,2762],{},"Zostanie dodana zależność do repozytorium znajdującym się pod adresem: ",[459,6281,6282],{},"https:\u002F\u002Fxperios.googlecode.com\u002Fsvn\u002Fmaven-repo"," o grupie ",[459,6285,6286],{},"pl.xperios",", artefakcie sample-project i wersji 1.0. Należy pamiętać aby identyfikator repositoryId zgadzał się z identyfikatorem w pliku ",[459,6289,6113],{},[984,6291,6292],{},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}",{"title":457,"searchDepth":471,"depth":471,"links":6294},[],"2012-02-07","Prezentacja sposobu instalacji artefaktu w zdalnym repozytorium z użyciem pluginu wagon",{"layout":993},"\u002Fblog\u002F2012-02-07-deploy-artifacts-to-the-repository",{"title":6003,"description":6296},"2.blog\u002F2012-02-07-deploy-artifacts-to-the-repository","v8ZYgjUpgq1PbBynOM2NixxE0DqGsCDstD4uS0TOLB8",{"id":6303,"title":6304,"authors":409,"badge":409,"body":6305,"date":6638,"description":6639,"extension":991,"image":409,"meta":6640,"navigation":474,"path":6641,"seo":6642,"stem":6643,"__hash__":6644},"posts\u002F2.blog\u002F2013-06-12-Synchronous-injection-of-Styles-to-UI-Binder.md","UI Binder GWT Styles",{"type":423,"value":6306,"toc":6636},[6307,6310,6313,6320,6323,6338,6341,6381,6384,6387,6393,6396,6401,6433,6436,6441,6460,6463,6487,6490,6499,6502,6511,6514,6519,6554,6557,6610,6613,6633],[426,6308,6309],{},"Often when using UI Binder in your GWT project you would like to stylize your app with CSS. There are two ways of doing this a) by adding CSS attribute directly in DOM element or b) by using Client Bundle.",[426,6311,6312],{},"#Add CSS attribute",[426,6314,6315,6316],{},"Please check reference guide: ",[977,6317,6318],{"href":6318,"rel":6319},"https:\u002F\u002Fdevelopers.google.com\u002Fweb-toolkit\u002Fdoc\u002Flatest\u002FDevGuideUiCss",[981],[426,6321,6322],{},"To add class attribute to any GWT element you need to use DOM static helper method. For example:",[452,6324,6326],{"className":598,"code":6325,"language":600,"meta":457,"style":457},"Button b = new Button();\nDOM.setElementAttribute(b.getElement(), \"id\", \"my-button-id\")\n",[459,6327,6328,6333],{"__ignoreMap":457},[462,6329,6330],{"class":464,"line":465},[462,6331,6332],{},"Button b = new Button();\n",[462,6334,6335],{"class":464,"line":471},[462,6336,6337],{},"DOM.setElementAttribute(b.getElement(), \"id\", \"my-button-id\")\n",[426,6339,6340],{},"Then in CSS file that you must add to the hosted page:",[452,6342,6346],{"className":6343,"code":6344,"language":6345,"meta":457,"style":457},"language-css shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","#my-button-id { \n    font-size: 100%; \n}\n","css",[459,6347,6348,6361,6377],{"__ignoreMap":457},[462,6349,6350,6353,6356,6359],{"class":464,"line":465},[462,6351,6352],{"class":4190},"#",[462,6354,6355],{"class":5513},"my-button-id",[462,6357,6358],{"class":4190}," {",[462,6360,6103],{"class":4186},[462,6362,6363,6367,6369,6372,6375],{"class":464,"line":471},[462,6364,6366],{"class":6365},"sqsOY","    font-size",[462,6368,3095],{"class":4190},[462,6370,6371],{"class":5513}," 100%",[462,6373,6374],{"class":4190},";",[462,6376,6103],{"class":4186},[462,6378,6379],{"class":464,"line":478},[462,6380,811],{"class":4190},[426,6382,6383],{},"Although it works it has some disadvantages. Lets talk now about another option.",[426,6385,6386],{},"#Client Bundle",[426,6388,6315,6389],{},[977,6390,6391],{"href":6391,"rel":6392},"https:\u002F\u002Fdevelopers.google.com\u002Fweb-toolkit\u002Fdoc\u002Flatest\u002FDevGuideClientBundle#CssResource",[981],[426,6394,6395],{},"Let’s define CSS file in project as resource without attaching it to the hosted page:",[426,6397,6398,3095],{},[459,6399,6400],{},"MyStyle.css",[452,6402,6404],{"className":6343,"code":6403,"language":6345,"meta":457,"style":457},".innerLayout {\n    background-color: black;\n}\n",[459,6405,6406,6416,6429],{"__ignoreMap":457},[462,6407,6408,6410,6413],{"class":464,"line":465},[462,6409,2762],{"class":4190},[462,6411,6412],{"class":3738},"innerLayout",[462,6414,6415],{"class":4190}," {\n",[462,6417,6418,6421,6423,6426],{"class":464,"line":471},[462,6419,6420],{"class":6365},"    background-color",[462,6422,3095],{"class":4190},[462,6424,6425],{"class":4186}," black",[462,6427,6428],{"class":4190},";\n",[462,6430,6431],{"class":464,"line":478},[462,6432,811],{"class":4190},[426,6434,6435],{},"Lets define it’s interface:",[426,6437,6438,3095],{},[459,6439,6440],{},"MyStyle.java",[452,6442,6444],{"className":598,"code":6443,"language":600,"meta":457,"style":457},"interface MyStyle extends CssResource {\n    String innerLayout();\n}\n",[459,6445,6446,6451,6456],{"__ignoreMap":457},[462,6447,6448],{"class":464,"line":465},[462,6449,6450],{},"interface MyStyle extends CssResource {\n",[462,6452,6453],{"class":464,"line":471},[462,6454,6455],{},"    String innerLayout();\n",[462,6457,6458],{"class":464,"line":478},[462,6459,811],{},[426,6461,6462],{},"And resources that contains styles:",[452,6464,6466],{"className":598,"code":6465,"language":600,"meta":457,"style":457},"interface MyResources extends ClientBundle {\n    @ClientBundle.Source(value = \"MyStyle.css\")\n    MyStyle style();\n}\n",[459,6467,6468,6473,6478,6483],{"__ignoreMap":457},[462,6469,6470],{"class":464,"line":465},[462,6471,6472],{},"interface MyResources extends ClientBundle {\n",[462,6474,6475],{"class":464,"line":471},[462,6476,6477],{},"    @ClientBundle.Source(value = \"MyStyle.css\")\n",[462,6479,6480],{"class":464,"line":478},[462,6481,6482],{},"    MyStyle style();\n",[462,6484,6485],{"class":464,"line":484},[462,6486,811],{},[426,6488,6489],{},"Now we can use it in our application:",[452,6491,6493],{"className":598,"code":6492,"language":600,"meta":457,"style":457},"Style style = GWT.\u003CResources> create(MyResources.class).style();\n",[459,6494,6495],{"__ignoreMap":457},[462,6496,6497],{"class":464,"line":465},[462,6498,6492],{},[426,6500,6501],{},"Very often we want to use style immediately so we must assure that styles are already injected to the application:",[452,6503,6505],{"className":598,"code":6504,"language":600,"meta":457,"style":457},"StyleInjector.inject(style.getText(), true);\n",[459,6506,6507],{"__ignoreMap":457},[462,6508,6509],{"class":464,"line":465},[462,6510,6504],{},[426,6512,6513],{},"What can can we do now with such style name? We can use it as in the previous example or it can be passed to UI Binder:",[426,6515,6516,3095],{},[459,6517,6518],{},"MyWidget.java",[452,6520,6522],{"className":454,"code":6521,"language":456,"meta":457,"style":457},"\u003Cui:UiBinder xmlns:ui=\"urn:ui:com.google.gwt.uibinder\" xmlns:g='urn:import:com.google.gwt.user.client.ui'>\n    \u003Cui:with field='style' type='....Style' \u002F>\n    \u003Cg:HTMLPanel>\n        \u003Cdiv class=\"{style.innerLayout}\">Text\u003C\u002Fdiv>\n    \u003C\u002Fg:HTMLPanel>\n\u003C\u002Fui:UiBinder>\n",[459,6523,6524,6529,6534,6539,6544,6549],{"__ignoreMap":457},[462,6525,6526],{"class":464,"line":465},[462,6527,6528],{},"\u003Cui:UiBinder xmlns:ui=\"urn:ui:com.google.gwt.uibinder\" xmlns:g='urn:import:com.google.gwt.user.client.ui'>\n",[462,6530,6531],{"class":464,"line":471},[462,6532,6533],{},"    \u003Cui:with field='style' type='....Style' \u002F>\n",[462,6535,6536],{"class":464,"line":478},[462,6537,6538],{},"    \u003Cg:HTMLPanel>\n",[462,6540,6541],{"class":464,"line":484},[462,6542,6543],{},"        \u003Cdiv class=\"{style.innerLayout}\">Text\u003C\u002Fdiv>\n",[462,6545,6546],{"class":464,"line":489},[462,6547,6548],{},"    \u003C\u002Fg:HTMLPanel>\n",[462,6550,6551],{"class":464,"line":495},[462,6552,6553],{},"\u003C\u002Fui:UiBinder>\n",[426,6555,6556],{},"There is much more effort using Client Bundle approach so why it’s better way? It depends what do you mean by better, but this allows you to according to the guide for:",[439,6558,6559,6562,6565,6568,6571,6574,6577,6580,6583,6586,6589,6592,6595,6598,6601,6604,6607],{},[442,6560,6561],{},"Validate CSS during compilation",[442,6563,6564],{},"Mimific and optimize output",[442,6566,6567],{},"Leverage GWT compiler",[442,6569,6570],{},"Different CSS for different browsers, automatically",[442,6572,6573],{},"Static evaluation of content",[442,6575,6576],{},"Basic CSS Modularization",[442,6578,6579],{},"Via dependency-injection API style",[442,6581,6582],{},"Widgets can inject their own CSS only when it’s needed",[442,6584,6585],{},"BiDi (Janus-style?)",[442,6587,6588],{},"CSS image strips",[442,6590,6591],{},"“Improve CSS”",[442,6593,6594],{},"Constants",[442,6596,6597],{},"Simple expressions",[442,6599,6600],{},"Runtime manipulation (StyleElement.setEnabled() handles many cases)",[442,6602,6603],{},"Compile-time class-name checking (Java\u002FCSS)",[442,6605,6606],{},"Obfuscation",[442,6608,6609],{},"Also when developing big project this allows to to keep resources clean and in right place.",[426,6611,6612],{},"#References",[439,6614,6615,6621,6627],{},[442,6616,6617],{},[977,6618,6619],{"href":6619,"rel":6620},"http:\u002F\u002Fwww.gwtproject.org\u002Fdoc\u002Flatest\u002FDevGuideClientBundle.html",[981],[442,6622,6623],{},[977,6624,6625],{"href":6625,"rel":6626},"https:\u002F\u002Fcode.google.com\u002Fp\u002Fgoogle-web-toolkit\u002Fwiki\u002FCssResource",[981],[442,6628,6629],{},[977,6630,6631],{"href":6631,"rel":6632},"https:\u002F\u002Fplus.google.com\u002Fu\u002F0\u002F+StefanoPulze\u002Fposts\u002FHEnf4qqChB7?cfem=1",[981],[984,6634,6635],{},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sqsOY, html code.shiki .sqsOY{--shiki-light:#8796B0;--shiki-default:#B2CCD6;--shiki-dark:#B2CCD6}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}",{"title":457,"searchDepth":471,"depth":471,"links":6637},[],"2013-06-12","Synchronous injection of Styles to UI Binder",{"layout":993},"\u002Fblog\u002F2013-06-12-synchronous-injection-of-styles-to-ui-binder",{"title":6304,"description":6639},"2.blog\u002F2013-06-12-Synchronous-injection-of-Styles-to-UI-Binder","4n1Fz2-7IrzteBZBLqVy5aJ_8pM_8z0OGed3GT5uAW8",{"id":6646,"title":6647,"authors":409,"badge":409,"body":6648,"date":7489,"description":7490,"extension":991,"image":409,"meta":7491,"navigation":474,"path":7492,"seo":7493,"stem":7494,"__hash__":7495},"posts\u002F2.blog\u002F2014-02-14-ExtJs-project-with-Netbeans.md","ExtJS project",{"type":423,"value":6649,"toc":7487},[6650,6653,6656,6659,6662,6665,6670,6673,6678,6681,6686,6689,6694,6701,6706,6709,6714,6717,6729,6732,6750,6755,6758,6765,6785,6788,6803,6809,7096,7102,7294,7297,7300,7303,7308,7311,7316,7319,7324,7327,7349,7352,7372,7375,7468,7475,7478,7484],[426,6651,6652],{},"Usually when it comes to develop Single Page Application (SPA) we choose GWT.  For simple apps we use native components, GWT-Bootstrap or custom components created with DOM utils. For Enterprise applications we don’t risk and go with GXT.",[426,6654,6655],{},"GXT is well done components library by Sencha for GWT that looks and behaves like their flag product – ExtJS. In this article we will leave Java world and for a while we will check how to create SPA applications in JavaScript with ExtJS.",[426,6657,6658],{},"For our purpose I will show how to develop simple application for Bids using Netbeans that has amazing support for many JS libraries included ExtJS.",[426,6660,6661],{},"#Prepare Netbeans project",[426,6663,6664],{},"Create new project:",[426,6666,6667],{},[3284,6668],{"alt":457,"src":6669},"\u002Fposts\u002Fassets\u002F2013-12-04-21_43_09-NetBeans-IDE-7.4.png",[426,6671,6672],{},"Create HTML5 project:",[426,6674,6675],{},[3284,6676],{"alt":457,"src":6677},"\u002Fposts\u002Fassets\u002F2013-12-04-21_44_16-New-Project.png",[426,6679,6680],{},"And call it BidProject:",[426,6682,6683],{},[3284,6684],{"alt":457,"src":6685},"\u002Fposts\u002Fassets\u002F2013-12-04-21_45_21-New-HTML5-Application.png",[426,6687,6688],{},"Next use empty template:",[426,6690,6691],{},[3284,6692],{"alt":457,"src":6693},"\u002Fposts\u002Fassets\u002F2013-12-04-21_46_27-New-HTML5-Application.png",[426,6695,6696,6697,6700],{},"Don’t add existing ExtJS as you will find only version ",[459,6698,6699],{},"3.4.1",". Netbeans uses external CdnJS service that allows to shuttle JS libraries to the project:",[426,6702,6703],{},[3284,6704],{"alt":457,"src":6705},"\u002Fposts\u002Fassets\u002F2013-12-04-21_52_57-NetBeans-IDE-7.4.png",[426,6707,6708],{},"The project now is ready:",[426,6710,6711],{},[3284,6712],{"alt":457,"src":6713},"\u002Fposts\u002Fassets\u002F2013-12-04-21_58_37-BidProject-NetBeans-IDE-7.4.png",[426,6715,6716],{},"#Add ExtJS library",[426,6718,6719,6720,6724,6725,6728],{},"Download the latst ExtJS library from here: ",[977,6721,6722],{"href":6722,"rel":6723},"http:\u002F\u002Fwww.sencha.com\u002Fproducts\u002Fextjs\u002Fdownload\u002F",[981],". In our case it is ",[459,6726,6727],{},"ExtJS 4.2.1",". Remember that ExtJS has dual license and for commercial project you must buy license.",[426,6730,6731],{},"Lets prepare project structure:",[6733,6734,6735,6738,6741,6744,6747],"ol",{},[442,6736,6737],{},"Extract file and copy resources to public_html folder of the project",[442,6739,6740],{},"Put ext-all-debug.js to extjs folder inside public_html folder",[442,6742,6743],{},"Create app folder inside public_html folder",[442,6745,6746],{},"Create empty file app.js inside public_html folder",[442,6748,6749],{},"The structure should look like this:",[426,6751,6752],{},[3284,6753],{"alt":457,"src":6754},"\u002Fposts\u002Fassets\u002F2013-12-04-22_27_46-BidProject-NetBeans-IDE-7.4.png",[426,6756,6757],{},"Now we need to add ExtJS and prepare an Entry point of our application:",[426,6759,6760,6761,6764],{},"Edit ",[459,6762,6763],{},"index.html"," and add ExtJs styles and library:",[452,6766,6768],{"className":454,"code":6767,"language":456,"meta":457,"style":457},"\u003C!--ExtJS-->\n\u003Clink rel=\"stylesheet\" type=\"text\u002Fcss\" href=\"resources\u002Fcss\u002Fext-all.css\">\n\u003Cscript type=\"text\u002Fjavascript\" src=\"extjs\u002Fext-all-debug.js\">\u003C\u002Fscript>\n",[459,6769,6770,6775,6780],{"__ignoreMap":457},[462,6771,6772],{"class":464,"line":465},[462,6773,6774],{},"\u003C!--ExtJS-->\n",[462,6776,6777],{"class":464,"line":471},[462,6778,6779],{},"\u003Clink rel=\"stylesheet\" type=\"text\u002Fcss\" href=\"resources\u002Fcss\u002Fext-all.css\">\n",[462,6781,6782],{"class":464,"line":478},[462,6783,6784],{},"\u003Cscript type=\"text\u002Fjavascript\" src=\"extjs\u002Fext-all-debug.js\">\u003C\u002Fscript>\n",[426,6786,6787],{},"next add entry point to the page:",[452,6789,6791],{"className":454,"code":6790,"language":456,"meta":457,"style":457},"    \u003C!--EntryPoint-->\n    \u003Cscript type=\"text\u002Fjavascript\" src=\"app.js\">\u003C\u002Fscript>\n",[459,6792,6793,6798],{"__ignoreMap":457},[462,6794,6795],{"class":464,"line":465},[462,6796,6797],{},"    \u003C!--EntryPoint-->\n",[462,6799,6800],{"class":464,"line":471},[462,6801,6802],{},"    \u003Cscript type=\"text\u002Fjavascript\" src=\"app.js\">\u003C\u002Fscript>\n",[426,6804,6805,6806,6808],{},"Entire ",[459,6807,6763],{}," should look like this:",[452,6810,6814],{"className":6811,"code":6812,"language":6813,"meta":457,"style":457},"language-html shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u003C!DOCTYPE html>\n\u003Chtml>\n  \u003Chead>\n    \u003Ctitle>BidProject\u003C\u002Ftitle>\n    \u003Cmeta charset=\"UTF-8\">\n    \u003Cmeta name=\"viewport\" content=\"width=device-width\">\n \n    \u003C!--ExtJS-->\n    \u003Clink rel=\"stylesheet\" type=\"text\u002Fcss\" href=\"resources\u002Fcss\u002Fext-all.css\">\n    \u003Cscript type=\"text\u002Fjavascript\" src=\"extjs\u002Fext-all-debug.js\">\u003C\u002Fscript>\n \n    \u003C!--EntryPoint-->\n    \u003Cscript type=\"text\u002Fjavascript\" src=\"app.js\">\u003C\u002Fscript>\n \n  \u003C\u002Fhead>\n  \u003Cbody>\n  \u003C\u002Fbody>\n\u003C\u002Fhtml>\n","html",[459,6815,6816,6832,6841,6851,6872,6894,6925,6929,6935,6980,7017,7021,7025,7058,7062,7071,7080,7088],{"__ignoreMap":457},[462,6817,6818,6821,6825,6829],{"class":464,"line":465},[462,6819,6820],{"class":4190},"\u003C!",[462,6822,6824],{"class":6823},"swJcz","DOCTYPE",[462,6826,6828],{"class":6827},"spNyl"," html",[462,6830,6831],{"class":4190},">\n",[462,6833,6834,6837,6839],{"class":464,"line":471},[462,6835,6836],{"class":4190},"\u003C",[462,6838,6813],{"class":6823},[462,6840,6831],{"class":4190},[462,6842,6843,6846,6849],{"class":464,"line":478},[462,6844,6845],{"class":4190},"  \u003C",[462,6847,6848],{"class":6823},"head",[462,6850,6831],{"class":4190},[462,6852,6853,6856,6859,6862,6865,6868,6870],{"class":464,"line":484},[462,6854,6855],{"class":4190},"    \u003C",[462,6857,6858],{"class":6823},"title",[462,6860,6861],{"class":4190},">",[462,6863,6864],{"class":4186},"BidProject",[462,6866,6867],{"class":4190},"\u003C\u002F",[462,6869,6858],{"class":6823},[462,6871,6831],{"class":4190},[462,6873,6874,6876,6879,6882,6884,6887,6890,6892],{"class":464,"line":489},[462,6875,6855],{"class":4190},[462,6877,6878],{"class":6823},"meta",[462,6880,6881],{"class":6827}," charset",[462,6883,4191],{"class":4190},[462,6885,6886],{"class":4190},"\"",[462,6888,6889],{"class":3742},"UTF-8",[462,6891,6886],{"class":4190},[462,6893,6831],{"class":4190},[462,6895,6896,6898,6900,6902,6904,6906,6909,6911,6914,6916,6918,6921,6923],{"class":464,"line":495},[462,6897,6855],{"class":4190},[462,6899,6878],{"class":6823},[462,6901,5529],{"class":6827},[462,6903,4191],{"class":4190},[462,6905,6886],{"class":4190},[462,6907,6908],{"class":3742},"viewport",[462,6910,6886],{"class":4190},[462,6912,6913],{"class":6827}," content",[462,6915,4191],{"class":4190},[462,6917,6886],{"class":4190},[462,6919,6920],{"class":3742},"width=device-width",[462,6922,6886],{"class":4190},[462,6924,6831],{"class":4190},[462,6926,6927],{"class":464,"line":501},[462,6928,6103],{"class":4186},[462,6930,6931],{"class":464,"line":506},[462,6932,6934],{"class":6933},"sHwdD","    \u003C!--ExtJS-->\n",[462,6936,6937,6939,6942,6945,6947,6949,6952,6954,6957,6959,6961,6964,6966,6969,6971,6973,6976,6978],{"class":464,"line":512},[462,6938,6855],{"class":4190},[462,6940,6941],{"class":6823},"link",[462,6943,6944],{"class":6827}," rel",[462,6946,4191],{"class":4190},[462,6948,6886],{"class":4190},[462,6950,6951],{"class":3742},"stylesheet",[462,6953,6886],{"class":4190},[462,6955,6956],{"class":6827}," type",[462,6958,4191],{"class":4190},[462,6960,6886],{"class":4190},[462,6962,6963],{"class":3742},"text\u002Fcss",[462,6965,6886],{"class":4190},[462,6967,6968],{"class":6827}," href",[462,6970,4191],{"class":4190},[462,6972,6886],{"class":4190},[462,6974,6975],{"class":3742},"resources\u002Fcss\u002Fext-all.css",[462,6977,6886],{"class":4190},[462,6979,6831],{"class":4190},[462,6981,6982,6984,6987,6989,6991,6993,6996,6998,7001,7003,7005,7008,7010,7013,7015],{"class":464,"line":518},[462,6983,6855],{"class":4190},[462,6985,6986],{"class":6823},"script",[462,6988,6956],{"class":6827},[462,6990,4191],{"class":4190},[462,6992,6886],{"class":4190},[462,6994,6995],{"class":3742},"text\u002Fjavascript",[462,6997,6886],{"class":4190},[462,6999,7000],{"class":6827}," src",[462,7002,4191],{"class":4190},[462,7004,6886],{"class":4190},[462,7006,7007],{"class":3742},"extjs\u002Fext-all-debug.js",[462,7009,6886],{"class":4190},[462,7011,7012],{"class":4190},">\u003C\u002F",[462,7014,6986],{"class":6823},[462,7016,6831],{"class":4190},[462,7018,7019],{"class":464,"line":524},[462,7020,6103],{"class":4186},[462,7022,7023],{"class":464,"line":530},[462,7024,6797],{"class":6933},[462,7026,7027,7029,7031,7033,7035,7037,7039,7041,7043,7045,7047,7050,7052,7054,7056],{"class":464,"line":536},[462,7028,6855],{"class":4190},[462,7030,6986],{"class":6823},[462,7032,6956],{"class":6827},[462,7034,4191],{"class":4190},[462,7036,6886],{"class":4190},[462,7038,6995],{"class":3742},[462,7040,6886],{"class":4190},[462,7042,7000],{"class":6827},[462,7044,4191],{"class":4190},[462,7046,6886],{"class":4190},[462,7048,7049],{"class":3742},"app.js",[462,7051,6886],{"class":4190},[462,7053,7012],{"class":4190},[462,7055,6986],{"class":6823},[462,7057,6831],{"class":4190},[462,7059,7060],{"class":464,"line":542},[462,7061,6103],{"class":4186},[462,7063,7064,7067,7069],{"class":464,"line":547},[462,7065,7066],{"class":4190},"  \u003C\u002F",[462,7068,6848],{"class":6823},[462,7070,6831],{"class":4190},[462,7072,7073,7075,7078],{"class":464,"line":553},[462,7074,6845],{"class":4190},[462,7076,7077],{"class":6823},"body",[462,7079,6831],{"class":4190},[462,7081,7082,7084,7086],{"class":464,"line":558},[462,7083,7066],{"class":4190},[462,7085,7077],{"class":6823},[462,7087,6831],{"class":4190},[462,7089,7090,7092,7094],{"class":464,"line":564},[462,7091,6867],{"class":4190},[462,7093,6813],{"class":6823},[462,7095,6831],{"class":4190},[426,7097,7098,7099,7101],{},"Now we add sample content to Entry Point that we could see first results. Edit file ",[459,7100,7049],{}," and add following content (don’t worry I will explain everything latter):",[452,7103,7107],{"className":7104,"code":7105,"language":7106,"meta":457,"style":457},"language-javascript shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","Ext.application({\n  name: 'Bidder',\n  appFolder: 'app',\n  launch: function() {\n    Ext.create('Ext.container.Viewport', {\n      layout: 'fit',\n      items: [\n        {\n          title: 'MainContainer',\n          html: 'Hello, world'\n        }\n      ]\n    });\n  }\n});\n","javascript",[459,7108,7109,7125,7144,7160,7175,7199,7215,7225,7230,7246,7261,7265,7270,7280,7285],{"__ignoreMap":457},[462,7110,7111,7114,7116,7119,7122],{"class":464,"line":465},[462,7112,7113],{"class":4186},"Ext",[462,7115,2762],{"class":4190},[462,7117,7118],{"class":4285},"application",[462,7120,7121],{"class":4186},"(",[462,7123,7124],{"class":4190},"{\n",[462,7126,7127,7130,7132,7135,7138,7141],{"class":464,"line":471},[462,7128,7129],{"class":6823},"  name",[462,7131,3095],{"class":4190},[462,7133,7134],{"class":4190}," '",[462,7136,7137],{"class":3742},"Bidder",[462,7139,7140],{"class":4190},"'",[462,7142,7143],{"class":4190},",\n",[462,7145,7146,7149,7151,7153,7156,7158],{"class":464,"line":478},[462,7147,7148],{"class":6823},"  appFolder",[462,7150,3095],{"class":4190},[462,7152,7134],{"class":4190},[462,7154,7155],{"class":3742},"app",[462,7157,7140],{"class":4190},[462,7159,7143],{"class":4190},[462,7161,7162,7165,7167,7170,7173],{"class":464,"line":484},[462,7163,7164],{"class":4285},"  launch",[462,7166,3095],{"class":4190},[462,7168,7169],{"class":6827}," function",[462,7171,7172],{"class":4190},"()",[462,7174,6415],{"class":4190},[462,7176,7177,7180,7182,7185,7187,7189,7192,7194,7197],{"class":464,"line":489},[462,7178,7179],{"class":4186},"    Ext",[462,7181,2762],{"class":4190},[462,7183,7184],{"class":4285},"create",[462,7186,7121],{"class":6823},[462,7188,7140],{"class":4190},[462,7190,7191],{"class":3742},"Ext.container.Viewport",[462,7193,7140],{"class":4190},[462,7195,7196],{"class":4190},",",[462,7198,6415],{"class":4190},[462,7200,7201,7204,7206,7208,7211,7213],{"class":464,"line":495},[462,7202,7203],{"class":6823},"      layout",[462,7205,3095],{"class":4190},[462,7207,7134],{"class":4190},[462,7209,7210],{"class":3742},"fit",[462,7212,7140],{"class":4190},[462,7214,7143],{"class":4190},[462,7216,7217,7220,7222],{"class":464,"line":501},[462,7218,7219],{"class":6823},"      items",[462,7221,3095],{"class":4190},[462,7223,7224],{"class":6823}," [\n",[462,7226,7227],{"class":464,"line":506},[462,7228,7229],{"class":4190},"        {\n",[462,7231,7232,7235,7237,7239,7242,7244],{"class":464,"line":512},[462,7233,7234],{"class":6823},"          title",[462,7236,3095],{"class":4190},[462,7238,7134],{"class":4190},[462,7240,7241],{"class":3742},"MainContainer",[462,7243,7140],{"class":4190},[462,7245,7143],{"class":4190},[462,7247,7248,7251,7253,7255,7258],{"class":464,"line":518},[462,7249,7250],{"class":6823},"          html",[462,7252,3095],{"class":4190},[462,7254,7134],{"class":4190},[462,7256,7257],{"class":3742},"Hello, world",[462,7259,7260],{"class":4190},"'\n",[462,7262,7263],{"class":464,"line":524},[462,7264,1077],{"class":4190},[462,7266,7267],{"class":464,"line":530},[462,7268,7269],{"class":6823},"      ]\n",[462,7271,7272,7275,7278],{"class":464,"line":536},[462,7273,7274],{"class":4190},"    }",[462,7276,7277],{"class":6823},")",[462,7279,6428],{"class":4190},[462,7281,7282],{"class":464,"line":542},[462,7283,7284],{"class":4190},"  }\n",[462,7286,7287,7290,7292],{"class":464,"line":547},[462,7288,7289],{"class":4190},"}",[462,7291,7277],{"class":4186},[462,7293,6428],{"class":4190},[426,7295,7296],{},"We are done now with configuring ExtJS",[426,7298,7299],{},"#Deploy and run application",[426,7301,7302],{},"From the toolbar menu choose destination, where you would like to preview application (in my case embedded browser that is the best for fast prototyping):",[426,7304,7305],{},[3284,7306],{"alt":457,"src":7307},"\u002Fposts\u002Fassets\u002F2013-12-04-23_05_49-BidProject-NetBeans-IDE-7.4.png",[426,7309,7310],{},"Then on toolbar press play button ![](\u002Fposts\u002Fassets\u002F2013-12-04-23_07_28-BidProject-NetBeans-IDE-7.4.png\" alt=\"Start Button) to run server. Results will be displayed below the code:",[426,7312,7313],{},[3284,7314],{"alt":457,"src":7315},"\u002Fposts\u002Fassets\u002F2013-12-04-23_11_24-.png",[426,7317,7318],{},"#Entry point",[426,7320,7321,7322,5144],{},"Now let’s explain some parts of Application Entry Point (",[459,7323,7049],{},[426,7325,7326],{},"To configure application you need to pass configuration object to Ext.define function:",[452,7328,7330],{"className":7104,"code":7329,"language":7106,"meta":457,"style":457},"Ext.application({});\n",[459,7331,7332],{"__ignoreMap":457},[462,7333,7334,7336,7338,7340,7342,7345,7347],{"class":464,"line":465},[462,7335,7113],{"class":4186},[462,7337,2762],{"class":4190},[462,7339,7118],{"class":4285},[462,7341,7121],{"class":4186},[462,7343,7344],{"class":4190},"{}",[462,7346,7277],{"class":4186},[462,7348,6428],{"class":4190},[426,7350,7351],{},"Basic configuration contains:",[439,7353,7354,7360,7366],{},[442,7355,7356,7359],{},[2994,7357,7358],{},"name",": ‘Bidder’ – application name, it will be used latter as a prefix for namespace",[442,7361,7362,7365],{},[2994,7363,7364],{},"appFolder",": ‘app’ – folder of the application components that will develop as our application grows. We will keep there our Views, Models, Controllers, Stores in package like (hierarhical) folder structure.",[442,7367,7368,7371],{},[2994,7369,7370],{},"launch"," – this is method (function) that will be called when application is ready to be initialized",[426,7373,7374],{},"When application is being initialized following code is being executed:",[452,7376,7378],{"className":7104,"code":7377,"language":7106,"meta":457,"style":457},"Ext.create('Ext.container.Viewport', {\n      layout: 'fit',\n      items: [\n        {\n          title: 'MainContainer',\n          html: 'Hello, world'\n        }\n      ]\n    });\n",[459,7379,7380,7400,7414,7422,7426,7440,7452,7456,7460],{"__ignoreMap":457},[462,7381,7382,7384,7386,7388,7390,7392,7394,7396,7398],{"class":464,"line":465},[462,7383,7113],{"class":4186},[462,7385,2762],{"class":4190},[462,7387,7184],{"class":4285},[462,7389,7121],{"class":4186},[462,7391,7140],{"class":4190},[462,7393,7191],{"class":3742},[462,7395,7140],{"class":4190},[462,7397,7196],{"class":4190},[462,7399,6415],{"class":4190},[462,7401,7402,7404,7406,7408,7410,7412],{"class":464,"line":471},[462,7403,7203],{"class":6823},[462,7405,3095],{"class":4190},[462,7407,7134],{"class":4190},[462,7409,7210],{"class":3742},[462,7411,7140],{"class":4190},[462,7413,7143],{"class":4190},[462,7415,7416,7418,7420],{"class":464,"line":478},[462,7417,7219],{"class":6823},[462,7419,3095],{"class":4190},[462,7421,7224],{"class":4186},[462,7423,7424],{"class":464,"line":484},[462,7425,7229],{"class":4190},[462,7427,7428,7430,7432,7434,7436,7438],{"class":464,"line":489},[462,7429,7234],{"class":6823},[462,7431,3095],{"class":4190},[462,7433,7134],{"class":4190},[462,7435,7241],{"class":3742},[462,7437,7140],{"class":4190},[462,7439,7143],{"class":4190},[462,7441,7442,7444,7446,7448,7450],{"class":464,"line":495},[462,7443,7250],{"class":6823},[462,7445,3095],{"class":4190},[462,7447,7134],{"class":4190},[462,7449,7257],{"class":3742},[462,7451,7260],{"class":4190},[462,7453,7454],{"class":464,"line":501},[462,7455,1077],{"class":4190},[462,7457,7458],{"class":464,"line":506},[462,7459,7269],{"class":4186},[462,7461,7462,7464,7466],{"class":464,"line":512},[462,7463,7274],{"class":4190},[462,7465,7277],{"class":4186},[462,7467,6428],{"class":4190},[426,7469,7470,7471,7474],{},"This code creates ",[459,7472,7473],{},"Viewport",". This is a container that fills whole widow body space and resizes when the size of the window changes. This is also unique container that adopts automatically to the body if no components are attached to the page body yet.",[426,7476,7477],{},"Containers are components that can contain many other components like Panels, TabPanels, AccordionPanels. Child elements are defined as objects of items array. They can lay inside the container according to the layout defined by layout property.",[426,7479,7480,7481,7483],{},"In our case ",[459,7482,7473],{}," has single panel that lays inside in fit manner. By default if the object doesn’t have defined type it renders Panel component that has title and html properties.",[984,7485,7486],{},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}",{"title":457,"searchDepth":471,"depth":471,"links":7488},[],"2014-02-14","Introduction to ExtJS framework with Netbeans IDE",{"layout":993},"\u002Fblog\u002F2014-02-14-extjs-project-with-netbeans",{"title":6647,"description":7490},"2.blog\u002F2014-02-14-ExtJs-project-with-Netbeans","sOYFvk5rF7sv9KIUxrOqhCiuo-hddS_CIo0uyZVzQSg",{"id":7497,"title":7498,"authors":409,"badge":409,"body":7499,"date":7913,"description":7914,"extension":991,"image":409,"meta":7915,"navigation":474,"path":7916,"seo":7917,"stem":7918,"__hash__":7919},"posts\u002F2.blog\u002F2014-02-27-stage-maven-archetypes-to-central-repository.md","Stage Maven archetypes to Central Repository",{"type":423,"value":7500,"toc":7911},[7501,7508,7511,7516,7564,7569,7572,7581,7651,7656,7688,7693,7714,7724,7734,7748,7753,7858,7863,7868,7908],[426,7502,7503,7504,2762],{},"In some future posts I will share how to configure environment for publishing archetypes to the Central Repositories. Basically most of the knowledge is present in the official documentation here: ",[977,7505,7506],{"href":7506,"rel":7507},"https:\u002F\u002Fdocs.sonatype.org\u002Fdisplay\u002FRepository\u002FSonatype+OSS+Maven+Repository+Usage+Guide",[981],[426,7509,7510],{},"In this post I will show how to stage your archetypes on already configured environment. The steps are ass follow:",[6733,7512,7513],{},[442,7514,7515],{},"Commit and push all changes to the repository:",[452,7517,7519],{"className":3729,"code":7518,"language":3731,"meta":457,"style":457},"git add --all\ngit commit -m \"Your message\"\ngit push origin master\n",[459,7520,7521,7532,7551],{"__ignoreMap":457},[462,7522,7523,7526,7529],{"class":464,"line":465},[462,7524,7525],{"class":3738},"git",[462,7527,7528],{"class":3742}," add",[462,7530,7531],{"class":3742}," --all\n",[462,7533,7534,7536,7539,7542,7545,7548],{"class":464,"line":471},[462,7535,7525],{"class":3738},[462,7537,7538],{"class":3742}," commit",[462,7540,7541],{"class":3742}," -m",[462,7543,7544],{"class":4190}," \"",[462,7546,7547],{"class":3742},"Your message",[462,7549,7550],{"class":4190},"\"\n",[462,7552,7553,7555,7558,7561],{"class":464,"line":478},[462,7554,7525],{"class":3738},[462,7556,7557],{"class":3742}," push",[462,7559,7560],{"class":3742}," origin",[462,7562,7563],{"class":3742}," master\n",[6733,7565,7566],{"start":471},[442,7567,7568],{},"On Windows cofigure and run ssh-agent:",[426,7570,7571],{},"When using Git with SSH you could encourage some issues on Windows platform. Git requiring a passphrase, but Maven has no way to specify an appropriate passphrase, so the releasing process that is described in the next step essentially hangs. Note that this problem is limited to Windows!",[6733,7573,7574],{},[442,7575,7576,7577,7580],{},"The solution is to run ssh-agent. This can be found in ",[459,7578,7579],{},"C:\\Program Files (x86)\\Git\\bin\\",". After you run it, it outputs some environment variables that you need to set. For example:",[452,7582,7584],{"className":3729,"code":7583,"language":3731,"meta":457,"style":457},"C:\\>ssh-agent\nSSH_AUTH_SOCK=\u002Ftmp\u002Fssh-LhiYjP7924\u002Fagent.7924; export SSH_AUTH_SOCK;\nSSH_AGENT_PID=2792; export SSH_AGENT_PID;\necho Agent pid 2792;\n",[459,7585,7586,7596,7616,7635],{"__ignoreMap":457},[462,7587,7588,7591,7593],{"class":464,"line":465},[462,7589,7590],{"class":3738},"C:\\",[462,7592,6861],{"class":4186},[462,7594,7595],{"class":3742},"ssh-agent\n",[462,7597,7598,7601,7603,7606,7608,7611,7614],{"class":464,"line":471},[462,7599,7600],{"class":4186},"SSH_AUTH_SOCK",[462,7602,4191],{"class":4190},[462,7604,7605],{"class":3742},"\u002Ftmp\u002Fssh-LhiYjP7924\u002Fagent.7924",[462,7607,6374],{"class":4190},[462,7609,7610],{"class":6827}," export",[462,7612,7613],{"class":4186}," SSH_AUTH_SOCK",[462,7615,6428],{"class":4190},[462,7617,7618,7621,7623,7626,7628,7630,7633],{"class":464,"line":478},[462,7619,7620],{"class":4186},"SSH_AGENT_PID",[462,7622,4191],{"class":4190},[462,7624,7625],{"class":3742},"2792",[462,7627,6374],{"class":4190},[462,7629,7610],{"class":6827},[462,7631,7632],{"class":4186}," SSH_AGENT_PID",[462,7634,6428],{"class":4190},[462,7636,7637,7640,7643,7646,7649],{"class":464,"line":484},[462,7638,7639],{"class":4285},"echo",[462,7641,7642],{"class":3742}," Agent",[462,7644,7645],{"class":3742}," pid",[462,7647,7648],{"class":5513}," 2792",[462,7650,6428],{"class":4190},[6733,7652,7653],{"start":471},[442,7654,7655],{},"Next you need to place these in your environment:",[452,7657,7659],{"className":3729,"code":7658,"language":3731,"meta":457,"style":457},"C:\\> set SSH_AUTH_SOCK=\u002Ftmp\u002Fssh-LhiYjP7924\u002Fagent.7924\nC:\\> set SSH_AGENT_PID=2792\n",[459,7660,7661,7674],{"__ignoreMap":457},[462,7662,7663,7665,7668,7671],{"class":464,"line":465},[462,7664,7590],{"class":3738},[462,7666,7667],{"class":4186},"> ",[462,7669,7670],{"class":3742},"set",[462,7672,7673],{"class":3742}," SSH_AUTH_SOCK=\u002Ftmp\u002Fssh-LhiYjP7924\u002Fagent.7924\n",[462,7675,7676,7678,7680,7682,7685],{"class":464,"line":471},[462,7677,7590],{"class":3738},[462,7679,7667],{"class":4186},[462,7681,7670],{"class":3742},[462,7683,7684],{"class":3742}," SSH_AGENT_PID=",[462,7686,7687],{"class":5513},"2792\n",[6733,7689,7690],{"start":478},[442,7691,7692],{},"Finally add the key file and enter your passphrase that will be stored:",[452,7694,7696],{"className":3729,"code":7695,"language":3731,"meta":457,"style":457},"C:\\> ssh-add \"\u002Fc\u002FUsers\u002FPiotr\u002F.ssh\u002Fid_rsa\" \n",[459,7697,7698],{"__ignoreMap":457},[462,7699,7700,7702,7704,7707,7709,7712],{"class":464,"line":465},[462,7701,7590],{"class":3738},[462,7703,7667],{"class":4186},[462,7705,7706],{"class":3742},"ssh-add",[462,7708,7544],{"class":4190},[462,7710,7711],{"class":3742},"\u002Fc\u002FUsers\u002FPiotr\u002F.ssh\u002Fid_rsa",[462,7713,7550],{"class":4190},[7715,7716,7717],"blockquote",{},[426,7718,7719,7720,7723],{},"If you are having trouble with getting it, just execute: ",[459,7721,7722],{},"git fetch origin master"," that will show you the prompt with the key file path.",[6733,7725,7726],{"start":478},[442,7727,7728,7729,7733],{},"Publishing Snapshots:\nPublishing Snapshots is possible only to ",[977,7730,7731],{"href":7731,"rel":7732},"https:\u002F\u002Foss.sonatype.org\u002Fcontent\u002Frepositories\u002Fsnapshots\u002F",[981]," repository. To perform it execute following command:",[452,7735,7737],{"className":3729,"code":7736,"language":3731,"meta":457,"style":457},"mvn clean deploy\n",[459,7738,7739],{"__ignoreMap":457},[462,7740,7741,7743,7745],{"class":464,"line":465},[462,7742,3992],{"class":3738},[462,7744,3998],{"class":3742},[462,7746,7747],{"class":3742}," deploy\n",[6733,7749,7750],{"start":484},[442,7751,7752],{},"Publishing Releases to Sonatype:",[452,7754,7756],{"className":3729,"code":7755,"language":3731,"meta":457,"style":457},"mvn release:clean\nmvn release:prepare \u002F\u002Fthis will publish tag in the trunk with Released version and prepare new SNAPSHOT version for next development\nmvn release:perform \u002F\u002Factually signs and uploads artefacts to Sonatype Staging repository\n",[459,7757,7758,7765,7825],{"__ignoreMap":457},[462,7759,7760,7762],{"class":464,"line":465},[462,7761,3992],{"class":3738},[462,7763,7764],{"class":3742}," release:clean\n",[462,7766,7767,7769,7772,7775,7778,7781,7784,7787,7790,7793,7796,7799,7802,7805,7808,7811,7814,7816,7819,7822],{"class":464,"line":471},[462,7768,3992],{"class":3738},[462,7770,7771],{"class":3742}," release:prepare",[462,7773,7774],{"class":3742}," \u002F\u002Fthis",[462,7776,7777],{"class":3742}," will",[462,7779,7780],{"class":3742}," publish",[462,7782,7783],{"class":3742}," tag",[462,7785,7786],{"class":3742}," in",[462,7788,7789],{"class":3742}," the",[462,7791,7792],{"class":3742}," trunk",[462,7794,7795],{"class":3742}," with",[462,7797,7798],{"class":3742}," Released",[462,7800,7801],{"class":3742}," version",[462,7803,7804],{"class":3742}," and",[462,7806,7807],{"class":3742}," prepare",[462,7809,7810],{"class":3742}," new",[462,7812,7813],{"class":3742}," SNAPSHOT",[462,7815,7801],{"class":3742},[462,7817,7818],{"class":3742}," for",[462,7820,7821],{"class":3742}," next",[462,7823,7824],{"class":3742}," development\n",[462,7826,7827,7829,7832,7835,7838,7840,7843,7846,7849,7852,7855],{"class":464,"line":478},[462,7828,3992],{"class":3738},[462,7830,7831],{"class":3742}," release:perform",[462,7833,7834],{"class":3742}," \u002F\u002Factually",[462,7836,7837],{"class":3742}," signs",[462,7839,7804],{"class":3742},[462,7841,7842],{"class":3742}," uploads",[462,7844,7845],{"class":3742}," artefacts",[462,7847,7848],{"class":3742}," to",[462,7850,7851],{"class":3742}," Sonatype",[462,7853,7854],{"class":3742}," Staging",[462,7856,7857],{"class":3742}," repository\n",[7715,7859,7860],{},[426,7861,7862],{},"All releases are being staged to Sonatype repository. They will have to be validated by Central repository rules and only then they could be transferred.",[6733,7864,7865],{"start":489},[442,7866,7867],{},"Validating and releasing artefacts to the Central Repository:",[439,7869,7870,7878,7884,7898,7905],{},[442,7871,7872,7873,7877],{},"Go to ",[977,7874,7875],{"href":7875,"rel":7876},"https:\u002F\u002Foss.sonatype.org\u002F",[981]," and login with your Sonatype credentials.",[442,7879,7872,7880,7883],{},[459,7881,7882],{},"Staging Repositories"," and select your repository. The staging repository name should look like your groupId without punctuation followed by a number (orgmygroupid-1000).  If you just finished performing your release, it may take a minute or two for the staging repository to appear on the Staging Repositories page.  Also, if there is a long listing of staging repositories with names like central_bundles-*, make sure that you scroll through the listing to find one that bears a name resembling your groupId.",[442,7885,7886,7887,7890,7891,7894,7895,2762],{},"Click ",[459,7888,7889],{},"Close"," Button and then in the prompt ",[459,7892,7893],{},"Confirm"," button. This step will close staging process and starts validating artefacts by Central Repository rules. If everything is OK after refreshing the grid, the status of should be ",[459,7896,7897],{},"Closed",[442,7899,7900,7901,7904],{},"If everything went OK and the staging status is closed you can release it by selecting ",[459,7902,7903],{},"Release"," button.",[442,7906,7907],{},"Now it will take some time when Sonatype will transfer all artefacts. This is asynchronous process and it's being performed every 2 hours.",[984,7909,7910],{},"html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}",{"title":457,"searchDepth":471,"depth":471,"links":7912},[],"2014-02-27","Using Sonatype tools for publishing Maven archetypes to Central Repository",{"layout":993},"\u002Fblog\u002F2014-02-27-stage-maven-archetypes-to-central-repository",{"title":7498,"description":7914},"2.blog\u002F2014-02-27-stage-maven-archetypes-to-central-repository","0IcoQKq6SbTA5hKCbfKeTkU6aCIQfEpoQE7AMLwpjDo",{"id":7921,"title":7922,"authors":409,"badge":409,"body":7923,"date":7991,"description":7992,"extension":991,"image":409,"meta":7993,"navigation":474,"path":7994,"seo":7995,"stem":7996,"__hash__":7997},"posts\u002F2.blog\u002F2014-03-22-super-dev-mode-recompile-with-shortcut.md","Super Dev Mode recompile with shortcut",{"type":423,"value":7924,"toc":7989},[7925,7928,7972,7978,7986],[426,7926,7927],{},"Instead of using bookmark to recompile GWT module in Super Dev Mode you can use shortcuts. Step by step:",[439,7929,7930,7938,7941,7947,7953,7969],{},[442,7931,7932,7933],{},"Install ",[977,7934,7937],{"href":7935,"rel":7936},"https:\u002F\u002Fchrome.google.com\u002Fwebstore\u002Fdetail\u002Fshortcut-manager\u002Fmgjjeipcdnnjhgodgjpfkffcejoljijf\u002Frelated?hl=en",[981],"Shortcut Manager",[442,7939,7940],{},"Add new shortcut:",[442,7942,7943,7944],{},"Shortcut key: ",[459,7945,7946],{},"ctrl+r",[442,7948,7949,7950],{},"Url pattern. For example: ",[459,7951,7952],{},"http:\u002F\u002Flocalhost:8080\u002FApp*",[442,7954,7955,7956,7962,7963,7966,7967],{},"Copy content of your bookmark and decode it from url form using for example (dencoder)",[462,7957,7958],{},[977,7959,7960],{"href":7960,"rel":7961},"http:\u002F\u002Fmeyerweb.com\u002Feric\u002Ftools\u002Fdencoder\u002F",[981]," and copy content that is surrounded with ",[459,7964,7965],{},"javascript:{"," and ",[459,7968,7289],{},[442,7970,7971],{},"Alternatively you can use this configuration and adopt it to your project:",[452,7973,7976],{"className":7974,"code":7975,"language":3262},[3260],"window.__gwt_bookmarklet_params = {server_url:'http:\u002F\u002Flocalhost:9876\u002F',module_name:'App'}; var s = document.createElement('script'); s.src = 'http:\u002F\u002Flocalhost:9876\u002Fdev_mode_on.js'; void(document.getElementsByTagName('head')[0].appendChild(s));\n",[459,7977,7975],{"__ignoreMap":457},[439,7979,7980,7983],{},[442,7981,7982],{},"Add description",[442,7984,7985],{},"Save it",[426,7987,7988],{},"Next time you want recompile use ctrl+r and voilà.",{"title":457,"searchDepth":471,"depth":471,"links":7990},[],"2014-03-22","How to use keyboard shortcut to recompile GWT application in Super Dev Mode",{"layout":993},"\u002Fblog\u002F2014-03-22-super-dev-mode-recompile-with-shortcut",{"title":7922,"description":7992},"2.blog\u002F2014-03-22-super-dev-mode-recompile-with-shortcut","Z6UaLQPiB7jGpXMVudbmIfx7dEdm5GHXeR_LGg0R8m4",{"id":7999,"title":8000,"authors":409,"badge":409,"body":8001,"date":10763,"description":10764,"extension":991,"image":409,"meta":10765,"navigation":474,"path":10766,"seo":10767,"stem":10768,"__hash__":10769},"posts\u002F2.blog\u002F2015-03-01-unit-tests-with-intern.md","Testing Node applications with Intern framework",{"type":423,"value":8002,"toc":10735},[8003,8008,8011,8014,8017,8022,8025,8031,8037,8107,8111,8116,8122,8126,8133,8139,8145,8333,8343,8347,8350,8355,8422,8425,8431,8434,8440,8447,8476,8480,8483,8487,8490,8496,8499,8505,8509,8515,8593,8599,8605,8609,8613,8616,8622,8626,8629,8635,8638,8644,8648,8654,8660,8827,8831,8834,8838,8843,9063,9076,9080,9083,9089,9092,9098,9102,9105,9125,9128,9131,9134,9137,9157,9160,9166,9314,9317,9323,9509,9514,9730,9733,9738,9741,9747,9753,9756,9762,9902,9905,9911,9914,9917,9920,10160,10163,10169,10172,10178,10324,10327,10333,10336,10339,10342,10345,10351,10705,10708,10719,10722,10725,10732],[8004,8005,8007],"h1",{"id":8006},"introduction","Introduction",[426,8009,8010],{},"In JS world, regressions may appear at every change without any warning, so tests are equally important as production code. The same rule applies to every non static typed languages, but let's stay on JS.",[426,8012,8013],{},"Intern is a complete framework for testing JavaScript Web sites and applications. I will use it to demostrate how to test NodeJS applications using intern framework. First I configure testing infrastructure so we could start writing business logic and testing it.",[426,8015,8016],{},"#Set up infrastructure",[8018,8019,8021],"h2",{"id":8020},"create-node-project","Create Node project",[426,8023,8024],{},"Create NodeJS project:",[452,8026,8029],{"className":8027,"code":8028,"language":3262},[3260],"mkdir intern-unit-tests\ncd intern-unit-tests\n",[459,8030,8028],{"__ignoreMap":457},[426,8032,8033,8034,3095],{},"Create init ",[459,8035,8036],{},"package.json",[452,8038,8042],{"className":8039,"code":8040,"language":8041,"meta":457,"style":457},"language-js shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","{\n  \"name\": \"intern-unit-tests\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\"\n}\n","js",[459,8043,8044,8048,8069,8089,8103],{"__ignoreMap":457},[462,8045,8046],{"class":464,"line":465},[462,8047,7124],{"class":4190},[462,8049,8050,8053,8055,8057,8060,8062,8065,8067],{"class":464,"line":471},[462,8051,8052],{"class":4190},"  \"",[462,8054,7358],{"class":3742},[462,8056,6886],{"class":4190},[462,8058,8059],{"class":6823},": ",[462,8061,6886],{"class":4190},[462,8063,8064],{"class":3742},"intern-unit-tests",[462,8066,6886],{"class":4190},[462,8068,7143],{"class":4190},[462,8070,8071,8073,8076,8078,8080,8082,8085,8087],{"class":464,"line":478},[462,8072,8052],{"class":4190},[462,8074,8075],{"class":3742},"version",[462,8077,6886],{"class":4190},[462,8079,8059],{"class":6823},[462,8081,6886],{"class":4190},[462,8083,8084],{"class":3742},"1.0.0",[462,8086,6886],{"class":4190},[462,8088,7143],{"class":4190},[462,8090,8091,8093,8096,8098,8100],{"class":464,"line":484},[462,8092,8052],{"class":4190},[462,8094,8095],{"class":3742},"description",[462,8097,6886],{"class":4190},[462,8099,8059],{"class":6823},[462,8101,8102],{"class":4190},"\"\"\n",[462,8104,8105],{"class":464,"line":489},[462,8106,811],{"class":4190},[8018,8108,8110],{"id":8109},"implementing-rest-endpoint-using-expressjs","Implementing REST endpoint using ExpressJS",[8112,8113,8115],"h3",{"id":8114},"install-expressjs","Install ExpressJS:",[452,8117,8120],{"className":8118,"code":8119,"language":3262},[3260],"npm install express --save-dev\n",[459,8121,8119],{"__ignoreMap":457},[8112,8123,8125],{"id":8124},"implement-application-endpoints","Implement application endpoints",[426,8127,8128,8129,8132],{},"We will create application code in ",[459,8130,8131],{},"src"," directory:",[452,8134,8137],{"className":8135,"code":8136,"language":3262},[3260],"mkdir src\n",[459,8138,8136],{"__ignoreMap":457},[426,8140,8141,8142,3095],{},"Create file: ",[459,8143,8144],{},"src\u002Fapp.js",[452,8146,8148],{"className":8039,"code":8147,"language":8041,"meta":457,"style":457},"var express = require('express');\nvar app = express();\n\napp.get('\u002Ftest', function (req, res) {\n    console.log('hitting test');\n    res.json({status: 'ok'});\n});\nconsole.log('App is configured');\nmodule.exports = app;\n",[459,8149,8150,8176,8192,8196,8234,8257,8290,8298,8320],{"__ignoreMap":457},[462,8151,8152,8155,8158,8160,8163,8165,8167,8170,8172,8174],{"class":464,"line":465},[462,8153,8154],{"class":6827},"var",[462,8156,8157],{"class":4186}," express ",[462,8159,4191],{"class":4190},[462,8161,8162],{"class":4285}," require",[462,8164,7121],{"class":4186},[462,8166,7140],{"class":4190},[462,8168,8169],{"class":3742},"express",[462,8171,7140],{"class":4190},[462,8173,7277],{"class":4186},[462,8175,6428],{"class":4190},[462,8177,8178,8180,8183,8185,8188,8190],{"class":464,"line":471},[462,8179,8154],{"class":6827},[462,8181,8182],{"class":4186}," app ",[462,8184,4191],{"class":4190},[462,8186,8187],{"class":4285}," express",[462,8189,7172],{"class":4186},[462,8191,6428],{"class":4190},[462,8193,8194],{"class":464,"line":478},[462,8195,475],{"emptyLinePlaceholder":474},[462,8197,8198,8200,8202,8205,8207,8209,8212,8214,8216,8218,8221,8225,8227,8230,8232],{"class":464,"line":484},[462,8199,7155],{"class":4186},[462,8201,2762],{"class":4190},[462,8203,8204],{"class":4285},"get",[462,8206,7121],{"class":4186},[462,8208,7140],{"class":4190},[462,8210,8211],{"class":3742},"\u002Ftest",[462,8213,7140],{"class":4190},[462,8215,7196],{"class":4190},[462,8217,7169],{"class":6827},[462,8219,8220],{"class":4190}," (",[462,8222,8224],{"class":8223},"sHdIc","req",[462,8226,7196],{"class":4190},[462,8228,8229],{"class":8223}," res",[462,8231,7277],{"class":4190},[462,8233,6415],{"class":4190},[462,8235,8236,8239,8241,8244,8246,8248,8251,8253,8255],{"class":464,"line":489},[462,8237,8238],{"class":4186},"    console",[462,8240,2762],{"class":4190},[462,8242,8243],{"class":4285},"log",[462,8245,7121],{"class":6823},[462,8247,7140],{"class":4190},[462,8249,8250],{"class":3742},"hitting test",[462,8252,7140],{"class":4190},[462,8254,7277],{"class":6823},[462,8256,6428],{"class":4190},[462,8258,8259,8262,8264,8267,8269,8272,8275,8277,8279,8282,8284,8286,8288],{"class":464,"line":495},[462,8260,8261],{"class":4186},"    res",[462,8263,2762],{"class":4190},[462,8265,8266],{"class":4285},"json",[462,8268,7121],{"class":6823},[462,8270,8271],{"class":4190},"{",[462,8273,8274],{"class":6823},"status",[462,8276,3095],{"class":4190},[462,8278,7134],{"class":4190},[462,8280,8281],{"class":3742},"ok",[462,8283,7140],{"class":4190},[462,8285,7289],{"class":4190},[462,8287,7277],{"class":6823},[462,8289,6428],{"class":4190},[462,8291,8292,8294,8296],{"class":464,"line":501},[462,8293,7289],{"class":4190},[462,8295,7277],{"class":4186},[462,8297,6428],{"class":4190},[462,8299,8300,8303,8305,8307,8309,8311,8314,8316,8318],{"class":464,"line":506},[462,8301,8302],{"class":4186},"console",[462,8304,2762],{"class":4190},[462,8306,8243],{"class":4285},[462,8308,7121],{"class":4186},[462,8310,7140],{"class":4190},[462,8312,8313],{"class":3742},"App is configured",[462,8315,7140],{"class":4190},[462,8317,7277],{"class":4186},[462,8319,6428],{"class":4190},[462,8321,8322,8325,8328,8331],{"class":464,"line":512},[462,8323,8324],{"class":4190},"module.exports",[462,8326,8327],{"class":4190}," =",[462,8329,8330],{"class":4186}," app",[462,8332,6428],{"class":4190},[426,8334,8335,8336,8338,8339,8342],{},"Above application hosts ",[459,8337,8211],{}," endpoint which returns JSON: ",[459,8340,8341],{},"{status: 'ok'}"," and logs activity each activity.",[8018,8344,8346],{"id":8345},"hosting-application-on-the-server","Hosting application on the server",[426,8348,8349],{},"To host that application we will need server.",[426,8351,8141,8352,3095],{},[459,8353,8354],{},"src\u002Fserver.js",[452,8356,8358],{"className":8039,"code":8357,"language":8041,"meta":457,"style":457},"var app = require('.\u002Fapp');\napp.listen(8080);\nconsole.log('Application is running on port 8080');\n",[459,8359,8360,8383,8401],{"__ignoreMap":457},[462,8361,8362,8364,8366,8368,8370,8372,8374,8377,8379,8381],{"class":464,"line":465},[462,8363,8154],{"class":6827},[462,8365,8182],{"class":4186},[462,8367,4191],{"class":4190},[462,8369,8162],{"class":4285},[462,8371,7121],{"class":4186},[462,8373,7140],{"class":4190},[462,8375,8376],{"class":3742},".\u002Fapp",[462,8378,7140],{"class":4190},[462,8380,7277],{"class":4186},[462,8382,6428],{"class":4190},[462,8384,8385,8387,8389,8392,8394,8397,8399],{"class":464,"line":471},[462,8386,7155],{"class":4186},[462,8388,2762],{"class":4190},[462,8390,8391],{"class":4285},"listen",[462,8393,7121],{"class":4186},[462,8395,8396],{"class":5513},"8080",[462,8398,7277],{"class":4186},[462,8400,6428],{"class":4190},[462,8402,8403,8405,8407,8409,8411,8413,8416,8418,8420],{"class":464,"line":478},[462,8404,8302],{"class":4186},[462,8406,2762],{"class":4190},[462,8408,8243],{"class":4285},[462,8410,7121],{"class":4186},[462,8412,7140],{"class":4190},[462,8414,8415],{"class":3742},"Application is running on port 8080",[462,8417,7140],{"class":4190},[462,8419,7277],{"class":4186},[462,8421,6428],{"class":4190},[426,8423,8424],{},"Lets run server:",[452,8426,8429],{"className":8427,"code":8428,"language":3262},[3260],"node src\u002Fserver\n",[459,8430,8428],{"__ignoreMap":457},[426,8432,8433],{},"Console output should display:",[452,8435,8438],{"className":8436,"code":8437,"language":3262},[3260],"App is configured\nApplication is running on port 8080\nhitting test\n",[459,8439,8437],{"__ignoreMap":457},[426,8441,8442,8443,8446],{},"And when hitting: ",[459,8444,8445],{},"http:\u002F\u002Flocalhost:8080\u002Ftest"," in the browser you should get:",[452,8448,8450],{"className":8039,"code":8449,"language":8041,"meta":457,"style":457},"{\n\"status\": \"ok\"\n}\n",[459,8451,8452,8456,8472],{"__ignoreMap":457},[462,8453,8454],{"class":464,"line":465},[462,8455,7124],{"class":4190},[462,8457,8458,8460,8462,8464,8466,8468,8470],{"class":464,"line":471},[462,8459,6886],{"class":4190},[462,8461,8274],{"class":3742},[462,8463,6886],{"class":4190},[462,8465,8059],{"class":6823},[462,8467,6886],{"class":4190},[462,8469,8281],{"class":3742},[462,8471,7550],{"class":4190},[462,8473,8474],{"class":464,"line":478},[462,8475,811],{"class":4190},[8018,8477,8479],{"id":8478},"install-and-initialize-grunt","Install and initialize Grunt",[426,8481,8482],{},"Before we start writing tests we need some test executor. For this purpose I use Grunt.",[8112,8484,8486],{"id":8485},"installing-grunt-dependencies","Installing Grunt dependencies",[426,8488,8489],{},"If you never used Grunt before you must first install it globally:",[452,8491,8494],{"className":8492,"code":8493,"language":3262},[3260],"npm install -g grunt\n",[459,8495,8493],{"__ignoreMap":457},[426,8497,8498],{},"Install Grunt locally:",[452,8500,8503],{"className":8501,"code":8502,"language":3262},[3260],"npm install grunt --save-dev\n",[459,8504,8502],{"__ignoreMap":457},[8112,8506,8508],{"id":8507},"grunt-configuration","Grunt configuration",[426,8510,8511,8512,3095],{},"Configure grunt, create ",[459,8513,8514],{},"Gruntfile.js",[452,8516,8518],{"className":8039,"code":8517,"language":8041,"meta":457,"style":457},"module.exports = function (grunt) {\n    grunt.initConfig({\n    });\n\n    grunt.registerTask('default', []);\n};\n",[459,8519,8520,8537,8551,8559,8563,8588],{"__ignoreMap":457},[462,8521,8522,8524,8526,8528,8530,8533,8535],{"class":464,"line":465},[462,8523,8324],{"class":4190},[462,8525,8327],{"class":4190},[462,8527,7169],{"class":6827},[462,8529,8220],{"class":4190},[462,8531,8532],{"class":8223},"grunt",[462,8534,7277],{"class":4190},[462,8536,6415],{"class":4190},[462,8538,8539,8542,8544,8547,8549],{"class":464,"line":471},[462,8540,8541],{"class":4186},"    grunt",[462,8543,2762],{"class":4190},[462,8545,8546],{"class":4285},"initConfig",[462,8548,7121],{"class":6823},[462,8550,7124],{"class":4190},[462,8552,8553,8555,8557],{"class":464,"line":478},[462,8554,7274],{"class":4190},[462,8556,7277],{"class":6823},[462,8558,6428],{"class":4190},[462,8560,8561],{"class":464,"line":484},[462,8562,475],{"emptyLinePlaceholder":474},[462,8564,8565,8567,8569,8572,8574,8576,8579,8581,8583,8586],{"class":464,"line":489},[462,8566,8541],{"class":4186},[462,8568,2762],{"class":4190},[462,8570,8571],{"class":4285},"registerTask",[462,8573,7121],{"class":6823},[462,8575,7140],{"class":4190},[462,8577,8578],{"class":3742},"default",[462,8580,7140],{"class":4190},[462,8582,7196],{"class":4190},[462,8584,8585],{"class":6823}," [])",[462,8587,6428],{"class":4190},[462,8589,8590],{"class":464,"line":495},[462,8591,8592],{"class":4190},"};\n",[426,8594,8595,8596,8598],{},"Now if you execute: ",[459,8597,8532],{}," you should have such console output:",[452,8600,8603],{"className":8601,"code":8602,"language":3262},[3260],"Done, without errors.\n",[459,8604,8602],{"__ignoreMap":457},[8018,8606,8608],{"id":8607},"install-and-configure-intern","Install and configure Intern",[8112,8610,8612],{"id":8611},"installing-intern-dependencies","Installing Intern dependencies",[426,8614,8615],{},"Install Intern dependency:",[452,8617,8620],{"className":8618,"code":8619,"language":3262},[3260],"npm install intern --save-dev\n",[459,8621,8619],{"__ignoreMap":457},[8112,8623,8625],{"id":8624},"intern-configuration","Intern configuration",[426,8627,8628],{},"Create tests directory:",[452,8630,8633],{"className":8631,"code":8632,"language":3262},[3260],"mkdir test\n",[459,8634,8632],{"__ignoreMap":457},[426,8636,8637],{},"Prepare intern configuration by copying example from intern directory:",[452,8639,8642],{"className":8640,"code":8641,"language":3262},[3260],"cp node_modules\u002Fintern\u002Ftests\u002Fexample.intern.js test\u002Fintern-config.js\n",[459,8643,8641],{"__ignoreMap":457},[8018,8645,8647],{"id":8646},"create-first-unit-test","Create first unit test",[452,8649,8652],{"className":8650,"code":8651,"language":3262},[3260],"mkdir test\u002Funit\n",[459,8653,8651],{"__ignoreMap":457},[426,8655,8656,8657,3095],{},"Create file, ",[459,8658,8659],{},"test\u002Funit\u002FappTest.js",[452,8661,8663],{"className":8039,"code":8662,"language":8041,"meta":457,"style":457},"define(function (require) {\n    var suite = require('intern!object');\n    var expect = require('intern\u002Fchai!expect');\n\n\n    suite({\n        ' strings': function () {\n            expect(\"Piotr\").to.equal('Piotr');\n        }\n    });\n});\n",[459,8664,8665,8684,8709,8733,8737,8741,8750,8769,8807,8811,8819],{"__ignoreMap":457},[462,8666,8667,8670,8672,8675,8677,8680,8682],{"class":464,"line":465},[462,8668,8669],{"class":4285},"define",[462,8671,7121],{"class":4186},[462,8673,8674],{"class":6827},"function",[462,8676,8220],{"class":4190},[462,8678,8679],{"class":8223},"require",[462,8681,7277],{"class":4190},[462,8683,6415],{"class":4190},[462,8685,8686,8689,8692,8694,8696,8698,8700,8703,8705,8707],{"class":464,"line":471},[462,8687,8688],{"class":6827},"    var",[462,8690,8691],{"class":4186}," suite",[462,8693,8327],{"class":4190},[462,8695,8162],{"class":4285},[462,8697,7121],{"class":6823},[462,8699,7140],{"class":4190},[462,8701,8702],{"class":3742},"intern!object",[462,8704,7140],{"class":4190},[462,8706,7277],{"class":6823},[462,8708,6428],{"class":4190},[462,8710,8711,8713,8716,8718,8720,8722,8724,8727,8729,8731],{"class":464,"line":478},[462,8712,8688],{"class":6827},[462,8714,8715],{"class":4186}," expect",[462,8717,8327],{"class":4190},[462,8719,8162],{"class":4285},[462,8721,7121],{"class":6823},[462,8723,7140],{"class":4190},[462,8725,8726],{"class":3742},"intern\u002Fchai!expect",[462,8728,7140],{"class":4190},[462,8730,7277],{"class":6823},[462,8732,6428],{"class":4190},[462,8734,8735],{"class":464,"line":484},[462,8736,475],{"emptyLinePlaceholder":474},[462,8738,8739],{"class":464,"line":489},[462,8740,475],{"emptyLinePlaceholder":474},[462,8742,8743,8746,8748],{"class":464,"line":495},[462,8744,8745],{"class":4285},"    suite",[462,8747,7121],{"class":6823},[462,8749,7124],{"class":4190},[462,8751,8752,8755,8758,8760,8762,8764,8767],{"class":464,"line":501},[462,8753,8754],{"class":4190},"        '",[462,8756,8757],{"class":6823}," strings",[462,8759,7140],{"class":4190},[462,8761,3095],{"class":4190},[462,8763,7169],{"class":6827},[462,8765,8766],{"class":4190}," ()",[462,8768,6415],{"class":4190},[462,8770,8771,8774,8776,8778,8781,8783,8785,8787,8790,8792,8795,8797,8799,8801,8803,8805],{"class":464,"line":506},[462,8772,8773],{"class":4285},"            expect",[462,8775,7121],{"class":6823},[462,8777,6886],{"class":4190},[462,8779,8780],{"class":3742},"Piotr",[462,8782,6886],{"class":4190},[462,8784,7277],{"class":6823},[462,8786,2762],{"class":4190},[462,8788,8789],{"class":4186},"to",[462,8791,2762],{"class":4190},[462,8793,8794],{"class":4285},"equal",[462,8796,7121],{"class":6823},[462,8798,7140],{"class":4190},[462,8800,8780],{"class":3742},[462,8802,7140],{"class":4190},[462,8804,7277],{"class":6823},[462,8806,6428],{"class":4190},[462,8808,8809],{"class":464,"line":512},[462,8810,1077],{"class":4190},[462,8812,8813,8815,8817],{"class":464,"line":518},[462,8814,7274],{"class":4190},[462,8816,7277],{"class":6823},[462,8818,6428],{"class":4190},[462,8820,8821,8823,8825],{"class":464,"line":524},[462,8822,7289],{"class":4190},[462,8824,7277],{"class":4186},[462,8826,6428],{"class":4190},[8018,8828,8830],{"id":8829},"execute-intern-tests-with-grunt","Execute Intern tests with Grunt",[426,8832,8833],{},"Now we are ready to prepare test executor.",[8112,8835,8837],{"id":8836},"configure-grunt","Configure Grunt",[426,8839,8840,8841,3095],{},"Lets modify ",[459,8842,8514],{},[452,8844,8846],{"className":8039,"code":8845,"language":8041,"meta":457,"style":457},"module.exports = function (grunt) {\n\n    grunt.initConfig({\n        intern: {\n            unit_testing: {\n                options: {\n                    config: 'test\u002Fintern-config',\n                    suites: ['test\u002Funit\u002FappTest']\n                }\n            }\n        }\n    });\n\n    grunt.loadNpmTasks('intern');\n\n    grunt.registerTask('default', ['test']);\n    grunt.registerTask('test', ['intern']);\n\n};\n\n",[459,8847,8848,8864,8868,8880,8889,8898,8907,8923,8943,8947,8951,8955,8963,8967,8989,8993,9025,9055,9059],{"__ignoreMap":457},[462,8849,8850,8852,8854,8856,8858,8860,8862],{"class":464,"line":465},[462,8851,8324],{"class":4190},[462,8853,8327],{"class":4190},[462,8855,7169],{"class":6827},[462,8857,8220],{"class":4190},[462,8859,8532],{"class":8223},[462,8861,7277],{"class":4190},[462,8863,6415],{"class":4190},[462,8865,8866],{"class":464,"line":471},[462,8867,475],{"emptyLinePlaceholder":474},[462,8869,8870,8872,8874,8876,8878],{"class":464,"line":478},[462,8871,8541],{"class":4186},[462,8873,2762],{"class":4190},[462,8875,8546],{"class":4285},[462,8877,7121],{"class":6823},[462,8879,7124],{"class":4190},[462,8881,8882,8885,8887],{"class":464,"line":484},[462,8883,8884],{"class":6823},"        intern",[462,8886,3095],{"class":4190},[462,8888,6415],{"class":4190},[462,8890,8891,8894,8896],{"class":464,"line":489},[462,8892,8893],{"class":6823},"            unit_testing",[462,8895,3095],{"class":4190},[462,8897,6415],{"class":4190},[462,8899,8900,8903,8905],{"class":464,"line":495},[462,8901,8902],{"class":6823},"                options",[462,8904,3095],{"class":4190},[462,8906,6415],{"class":4190},[462,8908,8909,8912,8914,8916,8919,8921],{"class":464,"line":501},[462,8910,8911],{"class":6823},"                    config",[462,8913,3095],{"class":4190},[462,8915,7134],{"class":4190},[462,8917,8918],{"class":3742},"test\u002Fintern-config",[462,8920,7140],{"class":4190},[462,8922,7143],{"class":4190},[462,8924,8925,8928,8930,8933,8935,8938,8940],{"class":464,"line":506},[462,8926,8927],{"class":6823},"                    suites",[462,8929,3095],{"class":4190},[462,8931,8932],{"class":6823}," [",[462,8934,7140],{"class":4190},[462,8936,8937],{"class":3742},"test\u002Funit\u002FappTest",[462,8939,7140],{"class":4190},[462,8941,8942],{"class":6823},"]\n",[462,8944,8945],{"class":464,"line":512},[462,8946,2696],{"class":4190},[462,8948,8949],{"class":464,"line":518},[462,8950,777],{"class":4190},[462,8952,8953],{"class":464,"line":524},[462,8954,1077],{"class":4190},[462,8956,8957,8959,8961],{"class":464,"line":530},[462,8958,7274],{"class":4190},[462,8960,7277],{"class":6823},[462,8962,6428],{"class":4190},[462,8964,8965],{"class":464,"line":536},[462,8966,475],{"emptyLinePlaceholder":474},[462,8968,8969,8971,8973,8976,8978,8980,8983,8985,8987],{"class":464,"line":542},[462,8970,8541],{"class":4186},[462,8972,2762],{"class":4190},[462,8974,8975],{"class":4285},"loadNpmTasks",[462,8977,7121],{"class":6823},[462,8979,7140],{"class":4190},[462,8981,8982],{"class":3742},"intern",[462,8984,7140],{"class":4190},[462,8986,7277],{"class":6823},[462,8988,6428],{"class":4190},[462,8990,8991],{"class":464,"line":547},[462,8992,475],{"emptyLinePlaceholder":474},[462,8994,8995,8997,8999,9001,9003,9005,9007,9009,9011,9013,9015,9018,9020,9023],{"class":464,"line":553},[462,8996,8541],{"class":4186},[462,8998,2762],{"class":4190},[462,9000,8571],{"class":4285},[462,9002,7121],{"class":6823},[462,9004,7140],{"class":4190},[462,9006,8578],{"class":3742},[462,9008,7140],{"class":4190},[462,9010,7196],{"class":4190},[462,9012,8932],{"class":6823},[462,9014,7140],{"class":4190},[462,9016,9017],{"class":3742},"test",[462,9019,7140],{"class":4190},[462,9021,9022],{"class":6823},"])",[462,9024,6428],{"class":4190},[462,9026,9027,9029,9031,9033,9035,9037,9039,9041,9043,9045,9047,9049,9051,9053],{"class":464,"line":558},[462,9028,8541],{"class":4186},[462,9030,2762],{"class":4190},[462,9032,8571],{"class":4285},[462,9034,7121],{"class":6823},[462,9036,7140],{"class":4190},[462,9038,9017],{"class":3742},[462,9040,7140],{"class":4190},[462,9042,7196],{"class":4190},[462,9044,8932],{"class":6823},[462,9046,7140],{"class":4190},[462,9048,8982],{"class":3742},[462,9050,7140],{"class":4190},[462,9052,9022],{"class":6823},[462,9054,6428],{"class":4190},[462,9056,9057],{"class":464,"line":564},[462,9058,475],{"emptyLinePlaceholder":474},[462,9060,9061],{"class":464,"line":693},[462,9062,8592],{"class":4190},[426,9064,9065,9066,9068,9069,9072,9073,9075],{},"This configuration loads ",[459,9067,8982],{}," task, configures ",[459,9070,9071],{},"intern:unit_testing"," task and assignes it to ",[459,9074,9017],{}," alias task.",[8112,9077,9079],{"id":9078},"executing-intern-tests","Executing Intern tests",[426,9081,9082],{},"Lets execute first unit task:",[452,9084,9087],{"className":9085,"code":9086,"language":3262},[3260],"grunt test\n",[459,9088,9086],{"__ignoreMap":457},[426,9090,9091],{},"With output:",[452,9093,9096],{"className":9094,"code":9095,"language":3262},[3260],"Running \"intern:unit_testing\" (intern) task\n>> PASS: main -  -  strings (0ms)\n>> 0\u002F1 tests failed\n>> 0\u002F1 tests failed\n",[459,9097,9095],{"__ignoreMap":457},[8018,9099,9101],{"id":9100},"summary","Summary",[426,9103,9104],{},"At this point we have configure:",[439,9106,9107,9113,9116,9119,9122],{},[442,9108,9109,9110,9112],{},"REST application with ",[459,9111,8211],{}," endpoint",[442,9114,9115],{},"Server that hosts that application",[442,9117,9118],{},"Configured task executor, and tasks configuration",[442,9120,9121],{},"Configured test framework with unit suites",[442,9123,9124],{},"Written first unit test which actually doesn't test application, but was made to check if everything works fine",[426,9126,9127],{},"Pretty much, isn't it?",[426,9129,9130],{},"#Implement business logic",[426,9132,9133],{},"At this point we have configured infrastructure that allows now to focus on business aspect of our application.\nWe will implement simple calculator service that will be called via http and return data as JSON. Mind that this method is no more REST as it focuses more on resources. I believe this way is more RPC.",[426,9135,9136],{},"I will follow best practices, so I will implement Calculator feature in TDD style. The sequence is:",[6733,9138,9139,9142,9145,9148,9151,9154],{},[442,9140,9141],{},"Write interface that will deliver business contract \u002F signature",[442,9143,9144],{},"Write simple test which uses business signature but doesn't pass as the method is not implemented",[442,9146,9147],{},"Implement business method to pass existing test",[442,9149,9150],{},"Write more complex test which doesn't pass",[442,9152,9153],{},"Fix test by modifying implementation",[442,9155,9156],{},"Refactor implementation",[8018,9158,9141],{"id":9159},"write-interface-that-will-deliver-business-contract-signature",[426,9161,9162,9163,3095],{},"Create business logic file ",[459,9164,9165],{},"src\u002Fcalculator.js",[452,9167,9169],{"className":8039,"code":9168,"language":8041,"meta":457,"style":457},"module.exports = {\n    \n    add: function(arg1, arg2){\n        return null;\n    },\n    subtract: function(arg1, arg2){\n        return null;\n    },\n    multiple: function(arg1, arg2){\n        return null;\n    },\n    divide: function(arg1, arg2){\n        return null;\n    }\n    \n}\n",[459,9170,9171,9179,9183,9205,9214,9219,9238,9244,9248,9267,9273,9277,9296,9302,9306,9310],{"__ignoreMap":457},[462,9172,9173,9175,9177],{"class":464,"line":465},[462,9174,8324],{"class":4190},[462,9176,8327],{"class":4190},[462,9178,6415],{"class":4190},[462,9180,9181],{"class":464,"line":471},[462,9182,5705],{"class":4186},[462,9184,9185,9188,9190,9192,9194,9197,9199,9202],{"class":464,"line":478},[462,9186,9187],{"class":4285},"    add",[462,9189,3095],{"class":4190},[462,9191,7169],{"class":6827},[462,9193,7121],{"class":4190},[462,9195,9196],{"class":8223},"arg1",[462,9198,7196],{"class":4190},[462,9200,9201],{"class":8223}," arg2",[462,9203,9204],{"class":4190},"){\n",[462,9206,9207,9211],{"class":464,"line":484},[462,9208,9210],{"class":9209},"s7zQu","        return",[462,9212,9213],{"class":4190}," null;\n",[462,9215,9216],{"class":464,"line":489},[462,9217,9218],{"class":4190},"    },\n",[462,9220,9221,9224,9226,9228,9230,9232,9234,9236],{"class":464,"line":495},[462,9222,9223],{"class":4285},"    subtract",[462,9225,3095],{"class":4190},[462,9227,7169],{"class":6827},[462,9229,7121],{"class":4190},[462,9231,9196],{"class":8223},[462,9233,7196],{"class":4190},[462,9235,9201],{"class":8223},[462,9237,9204],{"class":4190},[462,9239,9240,9242],{"class":464,"line":501},[462,9241,9210],{"class":9209},[462,9243,9213],{"class":4190},[462,9245,9246],{"class":464,"line":506},[462,9247,9218],{"class":4190},[462,9249,9250,9253,9255,9257,9259,9261,9263,9265],{"class":464,"line":512},[462,9251,9252],{"class":4285},"    multiple",[462,9254,3095],{"class":4190},[462,9256,7169],{"class":6827},[462,9258,7121],{"class":4190},[462,9260,9196],{"class":8223},[462,9262,7196],{"class":4190},[462,9264,9201],{"class":8223},[462,9266,9204],{"class":4190},[462,9268,9269,9271],{"class":464,"line":518},[462,9270,9210],{"class":9209},[462,9272,9213],{"class":4190},[462,9274,9275],{"class":464,"line":524},[462,9276,9218],{"class":4190},[462,9278,9279,9282,9284,9286,9288,9290,9292,9294],{"class":464,"line":530},[462,9280,9281],{"class":4285},"    divide",[462,9283,3095],{"class":4190},[462,9285,7169],{"class":6827},[462,9287,7121],{"class":4190},[462,9289,9196],{"class":8223},[462,9291,7196],{"class":4190},[462,9293,9201],{"class":8223},[462,9295,9204],{"class":4190},[462,9297,9298,9300],{"class":464,"line":536},[462,9299,9210],{"class":9209},[462,9301,9213],{"class":4190},[462,9303,9304],{"class":464,"line":542},[462,9305,702],{"class":4190},[462,9307,9308],{"class":464,"line":547},[462,9309,5705],{"class":4186},[462,9311,9312],{"class":464,"line":553},[462,9313,811],{"class":4190},[8018,9315,9144],{"id":9316},"write-simple-test-which-uses-business-signature-but-doesnt-pass-as-the-method-is-not-implemented",[426,9318,9319,9320,3095],{},"Create unit test file for business the file which holds the logic ",[459,9321,9322],{},"test\u002Funit\u002FcalculatorTest.js",[452,9324,9326],{"className":8039,"code":9325,"language":8041,"meta":457,"style":457},"define(function (require) {\n    var suite = require('intern!object');\n    var expect = require('intern\u002Fchai!expect');\n    var instance = require('intern\u002Fdojo\u002Fnode!..\u002F..\u002Fsrc\u002Fcalculator');\n\n\n    suite({\n        'should add 1 and 2 which equals 3': function () {\n            expect(instance.add(1,2)).to.equal(3);\n        }\n    });\n});\n",[459,9327,9328,9344,9366,9388,9412,9416,9420,9428,9445,9489,9493,9501],{"__ignoreMap":457},[462,9329,9330,9332,9334,9336,9338,9340,9342],{"class":464,"line":465},[462,9331,8669],{"class":4285},[462,9333,7121],{"class":4186},[462,9335,8674],{"class":6827},[462,9337,8220],{"class":4190},[462,9339,8679],{"class":8223},[462,9341,7277],{"class":4190},[462,9343,6415],{"class":4190},[462,9345,9346,9348,9350,9352,9354,9356,9358,9360,9362,9364],{"class":464,"line":471},[462,9347,8688],{"class":6827},[462,9349,8691],{"class":4186},[462,9351,8327],{"class":4190},[462,9353,8162],{"class":4285},[462,9355,7121],{"class":6823},[462,9357,7140],{"class":4190},[462,9359,8702],{"class":3742},[462,9361,7140],{"class":4190},[462,9363,7277],{"class":6823},[462,9365,6428],{"class":4190},[462,9367,9368,9370,9372,9374,9376,9378,9380,9382,9384,9386],{"class":464,"line":478},[462,9369,8688],{"class":6827},[462,9371,8715],{"class":4186},[462,9373,8327],{"class":4190},[462,9375,8162],{"class":4285},[462,9377,7121],{"class":6823},[462,9379,7140],{"class":4190},[462,9381,8726],{"class":3742},[462,9383,7140],{"class":4190},[462,9385,7277],{"class":6823},[462,9387,6428],{"class":4190},[462,9389,9390,9392,9395,9397,9399,9401,9403,9406,9408,9410],{"class":464,"line":484},[462,9391,8688],{"class":6827},[462,9393,9394],{"class":4186}," instance",[462,9396,8327],{"class":4190},[462,9398,8162],{"class":4285},[462,9400,7121],{"class":6823},[462,9402,7140],{"class":4190},[462,9404,9405],{"class":3742},"intern\u002Fdojo\u002Fnode!..\u002F..\u002Fsrc\u002Fcalculator",[462,9407,7140],{"class":4190},[462,9409,7277],{"class":6823},[462,9411,6428],{"class":4190},[462,9413,9414],{"class":464,"line":489},[462,9415,475],{"emptyLinePlaceholder":474},[462,9417,9418],{"class":464,"line":495},[462,9419,475],{"emptyLinePlaceholder":474},[462,9421,9422,9424,9426],{"class":464,"line":501},[462,9423,8745],{"class":4285},[462,9425,7121],{"class":6823},[462,9427,7124],{"class":4190},[462,9429,9430,9432,9435,9437,9439,9441,9443],{"class":464,"line":506},[462,9431,8754],{"class":4190},[462,9433,9434],{"class":6823},"should add 1 and 2 which equals 3",[462,9436,7140],{"class":4190},[462,9438,3095],{"class":4190},[462,9440,7169],{"class":6827},[462,9442,8766],{"class":4190},[462,9444,6415],{"class":4190},[462,9446,9447,9449,9451,9454,9456,9459,9461,9464,9466,9469,9472,9474,9476,9478,9480,9482,9485,9487],{"class":464,"line":512},[462,9448,8773],{"class":4285},[462,9450,7121],{"class":6823},[462,9452,9453],{"class":4186},"instance",[462,9455,2762],{"class":4190},[462,9457,9458],{"class":4285},"add",[462,9460,7121],{"class":6823},[462,9462,9463],{"class":5513},"1",[462,9465,7196],{"class":4190},[462,9467,9468],{"class":5513},"2",[462,9470,9471],{"class":6823},"))",[462,9473,2762],{"class":4190},[462,9475,8789],{"class":4186},[462,9477,2762],{"class":4190},[462,9479,8794],{"class":4285},[462,9481,7121],{"class":6823},[462,9483,9484],{"class":5513},"3",[462,9486,7277],{"class":6823},[462,9488,6428],{"class":4190},[462,9490,9491],{"class":464,"line":518},[462,9492,1077],{"class":4190},[462,9494,9495,9497,9499],{"class":464,"line":524},[462,9496,7274],{"class":4190},[462,9498,7277],{"class":6823},[462,9500,6428],{"class":4190},[462,9502,9503,9505,9507],{"class":464,"line":530},[462,9504,7289],{"class":4190},[462,9506,7277],{"class":4186},[462,9508,6428],{"class":4190},[426,9510,9511,9512,5144],{},"Now we must add this suite to the executions set in Grunt config file (",[459,9513,8514],{},[452,9515,9517],{"className":8039,"code":9516,"language":8041,"meta":457,"style":457},"module.exports = function (grunt) {\n\n    grunt.initConfig({\n        intern: {\n            unit_testing: {\n                options: {\n                    config: 'test\u002Fintern-config',\n                    suites: ['test\u002Funit\u002FappTest','test\u002Funit\u002FcalculatorTest']\n                }\n            }\n        }\n    });\n\n    grunt.loadNpmTasks('intern');\n\n    grunt.registerTask('default', ['test']);\n    grunt.registerTask('test', ['intern']);\n\n};\n",[459,9518,9519,9535,9539,9551,9559,9567,9575,9589,9614,9618,9622,9626,9634,9638,9658,9662,9692,9722,9726],{"__ignoreMap":457},[462,9520,9521,9523,9525,9527,9529,9531,9533],{"class":464,"line":465},[462,9522,8324],{"class":4190},[462,9524,8327],{"class":4190},[462,9526,7169],{"class":6827},[462,9528,8220],{"class":4190},[462,9530,8532],{"class":8223},[462,9532,7277],{"class":4190},[462,9534,6415],{"class":4190},[462,9536,9537],{"class":464,"line":471},[462,9538,475],{"emptyLinePlaceholder":474},[462,9540,9541,9543,9545,9547,9549],{"class":464,"line":478},[462,9542,8541],{"class":4186},[462,9544,2762],{"class":4190},[462,9546,8546],{"class":4285},[462,9548,7121],{"class":6823},[462,9550,7124],{"class":4190},[462,9552,9553,9555,9557],{"class":464,"line":484},[462,9554,8884],{"class":6823},[462,9556,3095],{"class":4190},[462,9558,6415],{"class":4190},[462,9560,9561,9563,9565],{"class":464,"line":489},[462,9562,8893],{"class":6823},[462,9564,3095],{"class":4190},[462,9566,6415],{"class":4190},[462,9568,9569,9571,9573],{"class":464,"line":495},[462,9570,8902],{"class":6823},[462,9572,3095],{"class":4190},[462,9574,6415],{"class":4190},[462,9576,9577,9579,9581,9583,9585,9587],{"class":464,"line":501},[462,9578,8911],{"class":6823},[462,9580,3095],{"class":4190},[462,9582,7134],{"class":4190},[462,9584,8918],{"class":3742},[462,9586,7140],{"class":4190},[462,9588,7143],{"class":4190},[462,9590,9591,9593,9595,9597,9599,9601,9603,9605,9607,9610,9612],{"class":464,"line":506},[462,9592,8927],{"class":6823},[462,9594,3095],{"class":4190},[462,9596,8932],{"class":6823},[462,9598,7140],{"class":4190},[462,9600,8937],{"class":3742},[462,9602,7140],{"class":4190},[462,9604,7196],{"class":4190},[462,9606,7140],{"class":4190},[462,9608,9609],{"class":3742},"test\u002Funit\u002FcalculatorTest",[462,9611,7140],{"class":4190},[462,9613,8942],{"class":6823},[462,9615,9616],{"class":464,"line":512},[462,9617,2696],{"class":4190},[462,9619,9620],{"class":464,"line":518},[462,9621,777],{"class":4190},[462,9623,9624],{"class":464,"line":524},[462,9625,1077],{"class":4190},[462,9627,9628,9630,9632],{"class":464,"line":530},[462,9629,7274],{"class":4190},[462,9631,7277],{"class":6823},[462,9633,6428],{"class":4190},[462,9635,9636],{"class":464,"line":536},[462,9637,475],{"emptyLinePlaceholder":474},[462,9639,9640,9642,9644,9646,9648,9650,9652,9654,9656],{"class":464,"line":542},[462,9641,8541],{"class":4186},[462,9643,2762],{"class":4190},[462,9645,8975],{"class":4285},[462,9647,7121],{"class":6823},[462,9649,7140],{"class":4190},[462,9651,8982],{"class":3742},[462,9653,7140],{"class":4190},[462,9655,7277],{"class":6823},[462,9657,6428],{"class":4190},[462,9659,9660],{"class":464,"line":547},[462,9661,475],{"emptyLinePlaceholder":474},[462,9663,9664,9666,9668,9670,9672,9674,9676,9678,9680,9682,9684,9686,9688,9690],{"class":464,"line":553},[462,9665,8541],{"class":4186},[462,9667,2762],{"class":4190},[462,9669,8571],{"class":4285},[462,9671,7121],{"class":6823},[462,9673,7140],{"class":4190},[462,9675,8578],{"class":3742},[462,9677,7140],{"class":4190},[462,9679,7196],{"class":4190},[462,9681,8932],{"class":6823},[462,9683,7140],{"class":4190},[462,9685,9017],{"class":3742},[462,9687,7140],{"class":4190},[462,9689,9022],{"class":6823},[462,9691,6428],{"class":4190},[462,9693,9694,9696,9698,9700,9702,9704,9706,9708,9710,9712,9714,9716,9718,9720],{"class":464,"line":558},[462,9695,8541],{"class":4186},[462,9697,2762],{"class":4190},[462,9699,8571],{"class":4285},[462,9701,7121],{"class":6823},[462,9703,7140],{"class":4190},[462,9705,9017],{"class":3742},[462,9707,7140],{"class":4190},[462,9709,7196],{"class":4190},[462,9711,8932],{"class":6823},[462,9713,7140],{"class":4190},[462,9715,8982],{"class":3742},[462,9717,7140],{"class":4190},[462,9719,9022],{"class":6823},[462,9721,6428],{"class":4190},[462,9723,9724],{"class":464,"line":564},[462,9725,475],{"emptyLinePlaceholder":474},[462,9727,9728],{"class":464,"line":693},[462,9729,8592],{"class":4190},[426,9731,9732],{},"And we can execute all tests:",[452,9734,9736],{"className":9735,"code":9086,"language":3262},[3260],[459,9737,9086],{"__ignoreMap":457},[426,9739,9740],{},"Which results in exception:",[452,9742,9745],{"className":9743,"code":9744,"language":3262},[3260],"Running \"intern:unit_testing\" (intern) task\n>> PASS: main -  -  strings (0ms)\n>> 0\u002F1 tests failed\n>> FAIL: main -  - should add 1 and 2 which equals 3 (1ms)\nAssertionError: expected null to equal 3\n\n",[459,9746,9744],{"__ignoreMap":457},[426,9748,9749,9750,9752],{},"We expected that as we didn't implemented ",[459,9751,9458],{}," method yet. We must write test first to prevent us from false positive situation.",[8018,9754,9147],{"id":9755},"implement-business-method-to-pass-existing-test",[426,9757,9758,9759,9761],{},"The simplest way to make test to pass is to return fixed 3. ",[459,9760,9165],{}," is now:",[452,9763,9765],{"className":8039,"code":9764,"language":8041,"meta":457,"style":457},"module.exports = {\n    \n    add: function(arg1, arg2){\n        return 3;\n    },\n    subtract: function(arg1, arg2){\n        return null;\n    },\n    multiple: function(arg1, arg2){\n        return null;\n    },\n    divide: function(arg1, arg2){\n        return null;\n    }\n    \n}\n",[459,9766,9767,9775,9779,9797,9806,9810,9828,9834,9838,9856,9862,9866,9884,9890,9894,9898],{"__ignoreMap":457},[462,9768,9769,9771,9773],{"class":464,"line":465},[462,9770,8324],{"class":4190},[462,9772,8327],{"class":4190},[462,9774,6415],{"class":4190},[462,9776,9777],{"class":464,"line":471},[462,9778,5705],{"class":4186},[462,9780,9781,9783,9785,9787,9789,9791,9793,9795],{"class":464,"line":478},[462,9782,9187],{"class":4285},[462,9784,3095],{"class":4190},[462,9786,7169],{"class":6827},[462,9788,7121],{"class":4190},[462,9790,9196],{"class":8223},[462,9792,7196],{"class":4190},[462,9794,9201],{"class":8223},[462,9796,9204],{"class":4190},[462,9798,9799,9801,9804],{"class":464,"line":484},[462,9800,9210],{"class":9209},[462,9802,9803],{"class":5513}," 3",[462,9805,6428],{"class":4190},[462,9807,9808],{"class":464,"line":489},[462,9809,9218],{"class":4190},[462,9811,9812,9814,9816,9818,9820,9822,9824,9826],{"class":464,"line":495},[462,9813,9223],{"class":4285},[462,9815,3095],{"class":4190},[462,9817,7169],{"class":6827},[462,9819,7121],{"class":4190},[462,9821,9196],{"class":8223},[462,9823,7196],{"class":4190},[462,9825,9201],{"class":8223},[462,9827,9204],{"class":4190},[462,9829,9830,9832],{"class":464,"line":501},[462,9831,9210],{"class":9209},[462,9833,9213],{"class":4190},[462,9835,9836],{"class":464,"line":506},[462,9837,9218],{"class":4190},[462,9839,9840,9842,9844,9846,9848,9850,9852,9854],{"class":464,"line":512},[462,9841,9252],{"class":4285},[462,9843,3095],{"class":4190},[462,9845,7169],{"class":6827},[462,9847,7121],{"class":4190},[462,9849,9196],{"class":8223},[462,9851,7196],{"class":4190},[462,9853,9201],{"class":8223},[462,9855,9204],{"class":4190},[462,9857,9858,9860],{"class":464,"line":518},[462,9859,9210],{"class":9209},[462,9861,9213],{"class":4190},[462,9863,9864],{"class":464,"line":524},[462,9865,9218],{"class":4190},[462,9867,9868,9870,9872,9874,9876,9878,9880,9882],{"class":464,"line":530},[462,9869,9281],{"class":4285},[462,9871,3095],{"class":4190},[462,9873,7169],{"class":6827},[462,9875,7121],{"class":4190},[462,9877,9196],{"class":8223},[462,9879,7196],{"class":4190},[462,9881,9201],{"class":8223},[462,9883,9204],{"class":4190},[462,9885,9886,9888],{"class":464,"line":536},[462,9887,9210],{"class":9209},[462,9889,9213],{"class":4190},[462,9891,9892],{"class":464,"line":542},[462,9893,702],{"class":4190},[462,9895,9896],{"class":464,"line":547},[462,9897,5705],{"class":4186},[462,9899,9900],{"class":464,"line":553},[462,9901,811],{"class":4190},[426,9903,9904],{},"And all tests are passing:",[452,9906,9909],{"className":9907,"code":9908,"language":3262},[3260],">> PASS: main -  - testing strings (0ms)\n>> 0\u002F1 tests failed\n>> PASS: main -  - should add 1 and 2 which equals 3 (0ms)\n>> 0\u002F1 tests failed\n>> 0\u002F2 tests failed\n",[459,9910,9908],{"__ignoreMap":457},[426,9912,9913],{},"You might ask WTF? why? how? but this is fake, that's bullshit!!!\nI know I know, but this is first very important step that you shouldn't omit in TDD. We start from tiny detail and then it will evolve. Sometimes it's very hard to implement feature at once and this is first step to incremental development. Lets move forward.",[8018,9915,9150],{"id":9916},"write-more-complex-test-which-doesnt-pass",[426,9918,9919],{},"Now we add another test case:",[452,9921,9923],{"className":8039,"code":9922,"language":8041,"meta":457,"style":457},"define(function (require) {\n    var suite = require('intern!object');\n    var expect = require('intern\u002Fchai!expect');\n    var instance = require('intern\u002Fdojo\u002Fnode!..\u002F..\u002Fsrc\u002Fcalculator');\n\n\n    suite({\n        'should add 1 and 2 which equals 3': function () {\n            expect(instance.add(1,2)).to.equal(3);\n        },\n        'should add 5 and 6 which equals 11': function () {\n            expect(instance.add(5,6)).to.equal(11);\n        }\n    });\n});\n\n",[459,9924,9925,9941,9963,9985,10007,10011,10015,10023,10039,10077,10082,10099,10140,10144,10152],{"__ignoreMap":457},[462,9926,9927,9929,9931,9933,9935,9937,9939],{"class":464,"line":465},[462,9928,8669],{"class":4285},[462,9930,7121],{"class":4186},[462,9932,8674],{"class":6827},[462,9934,8220],{"class":4190},[462,9936,8679],{"class":8223},[462,9938,7277],{"class":4190},[462,9940,6415],{"class":4190},[462,9942,9943,9945,9947,9949,9951,9953,9955,9957,9959,9961],{"class":464,"line":471},[462,9944,8688],{"class":6827},[462,9946,8691],{"class":4186},[462,9948,8327],{"class":4190},[462,9950,8162],{"class":4285},[462,9952,7121],{"class":6823},[462,9954,7140],{"class":4190},[462,9956,8702],{"class":3742},[462,9958,7140],{"class":4190},[462,9960,7277],{"class":6823},[462,9962,6428],{"class":4190},[462,9964,9965,9967,9969,9971,9973,9975,9977,9979,9981,9983],{"class":464,"line":478},[462,9966,8688],{"class":6827},[462,9968,8715],{"class":4186},[462,9970,8327],{"class":4190},[462,9972,8162],{"class":4285},[462,9974,7121],{"class":6823},[462,9976,7140],{"class":4190},[462,9978,8726],{"class":3742},[462,9980,7140],{"class":4190},[462,9982,7277],{"class":6823},[462,9984,6428],{"class":4190},[462,9986,9987,9989,9991,9993,9995,9997,9999,10001,10003,10005],{"class":464,"line":484},[462,9988,8688],{"class":6827},[462,9990,9394],{"class":4186},[462,9992,8327],{"class":4190},[462,9994,8162],{"class":4285},[462,9996,7121],{"class":6823},[462,9998,7140],{"class":4190},[462,10000,9405],{"class":3742},[462,10002,7140],{"class":4190},[462,10004,7277],{"class":6823},[462,10006,6428],{"class":4190},[462,10008,10009],{"class":464,"line":489},[462,10010,475],{"emptyLinePlaceholder":474},[462,10012,10013],{"class":464,"line":495},[462,10014,475],{"emptyLinePlaceholder":474},[462,10016,10017,10019,10021],{"class":464,"line":501},[462,10018,8745],{"class":4285},[462,10020,7121],{"class":6823},[462,10022,7124],{"class":4190},[462,10024,10025,10027,10029,10031,10033,10035,10037],{"class":464,"line":506},[462,10026,8754],{"class":4190},[462,10028,9434],{"class":6823},[462,10030,7140],{"class":4190},[462,10032,3095],{"class":4190},[462,10034,7169],{"class":6827},[462,10036,8766],{"class":4190},[462,10038,6415],{"class":4190},[462,10040,10041,10043,10045,10047,10049,10051,10053,10055,10057,10059,10061,10063,10065,10067,10069,10071,10073,10075],{"class":464,"line":512},[462,10042,8773],{"class":4285},[462,10044,7121],{"class":6823},[462,10046,9453],{"class":4186},[462,10048,2762],{"class":4190},[462,10050,9458],{"class":4285},[462,10052,7121],{"class":6823},[462,10054,9463],{"class":5513},[462,10056,7196],{"class":4190},[462,10058,9468],{"class":5513},[462,10060,9471],{"class":6823},[462,10062,2762],{"class":4190},[462,10064,8789],{"class":4186},[462,10066,2762],{"class":4190},[462,10068,8794],{"class":4285},[462,10070,7121],{"class":6823},[462,10072,9484],{"class":5513},[462,10074,7277],{"class":6823},[462,10076,6428],{"class":4190},[462,10078,10079],{"class":464,"line":518},[462,10080,10081],{"class":4190},"        },\n",[462,10083,10084,10086,10089,10091,10093,10095,10097],{"class":464,"line":524},[462,10085,8754],{"class":4190},[462,10087,10088],{"class":6823},"should add 5 and 6 which equals 11",[462,10090,7140],{"class":4190},[462,10092,3095],{"class":4190},[462,10094,7169],{"class":6827},[462,10096,8766],{"class":4190},[462,10098,6415],{"class":4190},[462,10100,10101,10103,10105,10107,10109,10111,10113,10116,10118,10121,10123,10125,10127,10129,10131,10133,10136,10138],{"class":464,"line":530},[462,10102,8773],{"class":4285},[462,10104,7121],{"class":6823},[462,10106,9453],{"class":4186},[462,10108,2762],{"class":4190},[462,10110,9458],{"class":4285},[462,10112,7121],{"class":6823},[462,10114,10115],{"class":5513},"5",[462,10117,7196],{"class":4190},[462,10119,10120],{"class":5513},"6",[462,10122,9471],{"class":6823},[462,10124,2762],{"class":4190},[462,10126,8789],{"class":4186},[462,10128,2762],{"class":4190},[462,10130,8794],{"class":4285},[462,10132,7121],{"class":6823},[462,10134,10135],{"class":5513},"11",[462,10137,7277],{"class":6823},[462,10139,6428],{"class":4190},[462,10141,10142],{"class":464,"line":536},[462,10143,1077],{"class":4190},[462,10145,10146,10148,10150],{"class":464,"line":542},[462,10147,7274],{"class":4190},[462,10149,7277],{"class":6823},[462,10151,6428],{"class":4190},[462,10153,10154,10156,10158],{"class":464,"line":547},[462,10155,7289],{"class":4190},[462,10157,7277],{"class":4186},[462,10159,6428],{"class":4190},[426,10161,10162],{},"which naturally doesn't pass:",[452,10164,10167],{"className":10165,"code":10166,"language":3262},[3260],">> PASS: main -  - testing strings (0ms)\n>> 0\u002F1 tests failed\n>> PASS: main -  - should add 1 and 2 which equals 3 (0ms)\n>> FAIL: main -  - should add 5 and 6 which equals 11 (1ms)\nAssertionError: expected 3 to equal 11\n",[459,10168,10166],{"__ignoreMap":457},[8018,10170,9153],{"id":10171},"fix-test-by-modifying-implementation",[426,10173,10174,10175,10177],{},"We are no longer able to put fixed numbers, so we need to implement ",[459,10176,9458],{}," method as simply it's possible:",[452,10179,10181],{"className":8039,"code":10180,"language":8041,"meta":457,"style":457},"module.exports = {\n    \n    add: function(arg1, arg2){\n        return arg1+arg2;\n    },\n    subtract: function(arg1, arg2){\n        return null;\n    },\n    multiple: function(arg1, arg2){\n        return null;\n    },\n    divide: function(arg1, arg2){\n        return null;\n    }\n    \n}\n",[459,10182,10183,10191,10195,10213,10228,10232,10250,10256,10260,10278,10284,10288,10306,10312,10316,10320],{"__ignoreMap":457},[462,10184,10185,10187,10189],{"class":464,"line":465},[462,10186,8324],{"class":4190},[462,10188,8327],{"class":4190},[462,10190,6415],{"class":4190},[462,10192,10193],{"class":464,"line":471},[462,10194,5705],{"class":4186},[462,10196,10197,10199,10201,10203,10205,10207,10209,10211],{"class":464,"line":478},[462,10198,9187],{"class":4285},[462,10200,3095],{"class":4190},[462,10202,7169],{"class":6827},[462,10204,7121],{"class":4190},[462,10206,9196],{"class":8223},[462,10208,7196],{"class":4190},[462,10210,9201],{"class":8223},[462,10212,9204],{"class":4190},[462,10214,10215,10217,10220,10223,10226],{"class":464,"line":484},[462,10216,9210],{"class":9209},[462,10218,10219],{"class":4186}," arg1",[462,10221,10222],{"class":4190},"+",[462,10224,10225],{"class":4186},"arg2",[462,10227,6428],{"class":4190},[462,10229,10230],{"class":464,"line":489},[462,10231,9218],{"class":4190},[462,10233,10234,10236,10238,10240,10242,10244,10246,10248],{"class":464,"line":495},[462,10235,9223],{"class":4285},[462,10237,3095],{"class":4190},[462,10239,7169],{"class":6827},[462,10241,7121],{"class":4190},[462,10243,9196],{"class":8223},[462,10245,7196],{"class":4190},[462,10247,9201],{"class":8223},[462,10249,9204],{"class":4190},[462,10251,10252,10254],{"class":464,"line":501},[462,10253,9210],{"class":9209},[462,10255,9213],{"class":4190},[462,10257,10258],{"class":464,"line":506},[462,10259,9218],{"class":4190},[462,10261,10262,10264,10266,10268,10270,10272,10274,10276],{"class":464,"line":512},[462,10263,9252],{"class":4285},[462,10265,3095],{"class":4190},[462,10267,7169],{"class":6827},[462,10269,7121],{"class":4190},[462,10271,9196],{"class":8223},[462,10273,7196],{"class":4190},[462,10275,9201],{"class":8223},[462,10277,9204],{"class":4190},[462,10279,10280,10282],{"class":464,"line":518},[462,10281,9210],{"class":9209},[462,10283,9213],{"class":4190},[462,10285,10286],{"class":464,"line":524},[462,10287,9218],{"class":4190},[462,10289,10290,10292,10294,10296,10298,10300,10302,10304],{"class":464,"line":530},[462,10291,9281],{"class":4285},[462,10293,3095],{"class":4190},[462,10295,7169],{"class":6827},[462,10297,7121],{"class":4190},[462,10299,9196],{"class":8223},[462,10301,7196],{"class":4190},[462,10303,9201],{"class":8223},[462,10305,9204],{"class":4190},[462,10307,10308,10310],{"class":464,"line":536},[462,10309,9210],{"class":9209},[462,10311,9213],{"class":4190},[462,10313,10314],{"class":464,"line":542},[462,10315,702],{"class":4190},[462,10317,10318],{"class":464,"line":547},[462,10319,5705],{"class":4186},[462,10321,10322],{"class":464,"line":553},[462,10323,811],{"class":4190},[426,10325,10326],{},"Now the test again passess:",[452,10328,10331],{"className":10329,"code":10330,"language":3262},[3260],"Running \"intern:unit_testing\" (intern) task\n>> PASS: main -  - testing strings (0ms)\n>> 0\u002F1 tests failed\n>> PASS: main -  - should add 1 and 2 which equals 3 (0ms)\n>> PASS: main -  - should add 5 and 6 which equals 11 (0ms)\n>> 0\u002F2 tests failed\n>> 0\u002F3 tests failed\n",[459,10332,10330],{"__ignoreMap":457},[8018,10334,9156],{"id":10335},"refactor-implementation",[426,10337,10338],{},"If above code makes complex you should refactor it. If not implement the rest methods in the same way starting again from the 1'th point.\nIf all features are implemented we can start integrating calculator module with the rest of application.",[426,10340,10341],{},"#Integration",[426,10343,10344],{},"After implemented and tested code we can integrate it with other components of our application. Other components also should be unit tested. In this step we will expose our calculator method as a Web Service.",[426,10346,10347,10348,10350],{},"In ",[459,10349,8144],{}," modify code:",[452,10352,10354],{"className":8039,"code":10353,"language":8041,"meta":457,"style":457},"var express = require('express');\nvar calculator = require('.\u002Fcalculator');\nvar app = express();\n\napp.get('\u002Ftest', function (req, res) {\n    console.log('hitting test');\n    res.json({status: 'ok'});\n});\n\napp.get('\u002Fcalculator\u002Fadd', function (req, res) {\n    \n    var param1Int = parseInt(req.query.arg1);\n    var param2Int = parseInt(req.query.arg2);\n    \n    var addResult = calculator.add(param1Int, param2Int);\n    \n    res.json({result: addResult});\n});\nconsole.log('App is configured');\nmodule.exports = app;\n",[459,10355,10356,10378,10402,10416,10420,10452,10472,10500,10508,10512,10545,10549,10578,10605,10609,10638,10642,10667,10675,10695],{"__ignoreMap":457},[462,10357,10358,10360,10362,10364,10366,10368,10370,10372,10374,10376],{"class":464,"line":465},[462,10359,8154],{"class":6827},[462,10361,8157],{"class":4186},[462,10363,4191],{"class":4190},[462,10365,8162],{"class":4285},[462,10367,7121],{"class":4186},[462,10369,7140],{"class":4190},[462,10371,8169],{"class":3742},[462,10373,7140],{"class":4190},[462,10375,7277],{"class":4186},[462,10377,6428],{"class":4190},[462,10379,10380,10382,10385,10387,10389,10391,10393,10396,10398,10400],{"class":464,"line":471},[462,10381,8154],{"class":6827},[462,10383,10384],{"class":4186}," calculator ",[462,10386,4191],{"class":4190},[462,10388,8162],{"class":4285},[462,10390,7121],{"class":4186},[462,10392,7140],{"class":4190},[462,10394,10395],{"class":3742},".\u002Fcalculator",[462,10397,7140],{"class":4190},[462,10399,7277],{"class":4186},[462,10401,6428],{"class":4190},[462,10403,10404,10406,10408,10410,10412,10414],{"class":464,"line":478},[462,10405,8154],{"class":6827},[462,10407,8182],{"class":4186},[462,10409,4191],{"class":4190},[462,10411,8187],{"class":4285},[462,10413,7172],{"class":4186},[462,10415,6428],{"class":4190},[462,10417,10418],{"class":464,"line":484},[462,10419,475],{"emptyLinePlaceholder":474},[462,10421,10422,10424,10426,10428,10430,10432,10434,10436,10438,10440,10442,10444,10446,10448,10450],{"class":464,"line":489},[462,10423,7155],{"class":4186},[462,10425,2762],{"class":4190},[462,10427,8204],{"class":4285},[462,10429,7121],{"class":4186},[462,10431,7140],{"class":4190},[462,10433,8211],{"class":3742},[462,10435,7140],{"class":4190},[462,10437,7196],{"class":4190},[462,10439,7169],{"class":6827},[462,10441,8220],{"class":4190},[462,10443,8224],{"class":8223},[462,10445,7196],{"class":4190},[462,10447,8229],{"class":8223},[462,10449,7277],{"class":4190},[462,10451,6415],{"class":4190},[462,10453,10454,10456,10458,10460,10462,10464,10466,10468,10470],{"class":464,"line":495},[462,10455,8238],{"class":4186},[462,10457,2762],{"class":4190},[462,10459,8243],{"class":4285},[462,10461,7121],{"class":6823},[462,10463,7140],{"class":4190},[462,10465,8250],{"class":3742},[462,10467,7140],{"class":4190},[462,10469,7277],{"class":6823},[462,10471,6428],{"class":4190},[462,10473,10474,10476,10478,10480,10482,10484,10486,10488,10490,10492,10494,10496,10498],{"class":464,"line":501},[462,10475,8261],{"class":4186},[462,10477,2762],{"class":4190},[462,10479,8266],{"class":4285},[462,10481,7121],{"class":6823},[462,10483,8271],{"class":4190},[462,10485,8274],{"class":6823},[462,10487,3095],{"class":4190},[462,10489,7134],{"class":4190},[462,10491,8281],{"class":3742},[462,10493,7140],{"class":4190},[462,10495,7289],{"class":4190},[462,10497,7277],{"class":6823},[462,10499,6428],{"class":4190},[462,10501,10502,10504,10506],{"class":464,"line":506},[462,10503,7289],{"class":4190},[462,10505,7277],{"class":4186},[462,10507,6428],{"class":4190},[462,10509,10510],{"class":464,"line":512},[462,10511,475],{"emptyLinePlaceholder":474},[462,10513,10514,10516,10518,10520,10522,10524,10527,10529,10531,10533,10535,10537,10539,10541,10543],{"class":464,"line":518},[462,10515,7155],{"class":4186},[462,10517,2762],{"class":4190},[462,10519,8204],{"class":4285},[462,10521,7121],{"class":4186},[462,10523,7140],{"class":4190},[462,10525,10526],{"class":3742},"\u002Fcalculator\u002Fadd",[462,10528,7140],{"class":4190},[462,10530,7196],{"class":4190},[462,10532,7169],{"class":6827},[462,10534,8220],{"class":4190},[462,10536,8224],{"class":8223},[462,10538,7196],{"class":4190},[462,10540,8229],{"class":8223},[462,10542,7277],{"class":4190},[462,10544,6415],{"class":4190},[462,10546,10547],{"class":464,"line":524},[462,10548,5705],{"class":6823},[462,10550,10551,10553,10556,10558,10561,10563,10565,10567,10570,10572,10574,10576],{"class":464,"line":530},[462,10552,8688],{"class":6827},[462,10554,10555],{"class":4186}," param1Int",[462,10557,8327],{"class":4190},[462,10559,10560],{"class":4285}," parseInt",[462,10562,7121],{"class":6823},[462,10564,8224],{"class":4186},[462,10566,2762],{"class":4190},[462,10568,10569],{"class":4186},"query",[462,10571,2762],{"class":4190},[462,10573,9196],{"class":4186},[462,10575,7277],{"class":6823},[462,10577,6428],{"class":4190},[462,10579,10580,10582,10585,10587,10589,10591,10593,10595,10597,10599,10601,10603],{"class":464,"line":536},[462,10581,8688],{"class":6827},[462,10583,10584],{"class":4186}," param2Int",[462,10586,8327],{"class":4190},[462,10588,10560],{"class":4285},[462,10590,7121],{"class":6823},[462,10592,8224],{"class":4186},[462,10594,2762],{"class":4190},[462,10596,10569],{"class":4186},[462,10598,2762],{"class":4190},[462,10600,10225],{"class":4186},[462,10602,7277],{"class":6823},[462,10604,6428],{"class":4190},[462,10606,10607],{"class":464,"line":542},[462,10608,5705],{"class":6823},[462,10610,10611,10613,10616,10618,10621,10623,10625,10627,10630,10632,10634,10636],{"class":464,"line":547},[462,10612,8688],{"class":6827},[462,10614,10615],{"class":4186}," addResult",[462,10617,8327],{"class":4190},[462,10619,10620],{"class":4186}," calculator",[462,10622,2762],{"class":4190},[462,10624,9458],{"class":4285},[462,10626,7121],{"class":6823},[462,10628,10629],{"class":4186},"param1Int",[462,10631,7196],{"class":4190},[462,10633,10584],{"class":4186},[462,10635,7277],{"class":6823},[462,10637,6428],{"class":4190},[462,10639,10640],{"class":464,"line":553},[462,10641,5705],{"class":6823},[462,10643,10644,10646,10648,10650,10652,10654,10657,10659,10661,10663,10665],{"class":464,"line":558},[462,10645,8261],{"class":4186},[462,10647,2762],{"class":4190},[462,10649,8266],{"class":4285},[462,10651,7121],{"class":6823},[462,10653,8271],{"class":4190},[462,10655,10656],{"class":6823},"result",[462,10658,3095],{"class":4190},[462,10660,10615],{"class":4186},[462,10662,7289],{"class":4190},[462,10664,7277],{"class":6823},[462,10666,6428],{"class":4190},[462,10668,10669,10671,10673],{"class":464,"line":564},[462,10670,7289],{"class":4190},[462,10672,7277],{"class":4186},[462,10674,6428],{"class":4190},[462,10676,10677,10679,10681,10683,10685,10687,10689,10691,10693],{"class":464,"line":693},[462,10678,8302],{"class":4186},[462,10680,2762],{"class":4190},[462,10682,8243],{"class":4285},[462,10684,7121],{"class":4186},[462,10686,7140],{"class":4190},[462,10688,8313],{"class":3742},[462,10690,7140],{"class":4190},[462,10692,7277],{"class":4186},[462,10694,6428],{"class":4190},[462,10696,10697,10699,10701,10703],{"class":464,"line":699},[462,10698,8324],{"class":4190},[462,10700,8327],{"class":4190},[462,10702,8330],{"class":4186},[462,10704,6428],{"class":4190},[426,10706,10707],{},"As you can see we are using calculator instead having business logic inside endpoints handlers. Benefits:",[439,10709,10710,10713,10716],{},[442,10711,10712],{},"Business logic is encapsulated in own module",[442,10714,10715],{},"The module is covered with unit tests",[442,10717,10718],{},"The module can be reused in other parts of the application",[8004,10720,9101],{"id":10721},"summary-1",[426,10723,10724],{},"In this post I demonstrated how to set up testing environment for NodeJS application using Intern framework and Grunt task runner.\nLiterally just with few lines of code we can have tested our application with unit tests which are almost equally important as production code.\nThe next step is to test if our integration was success, but this will be covered in the next post.",[426,10726,10727,10728],{},"Source code: ",[977,10729,10730],{"href":10730,"rel":10731},"https:\u002F\u002Fgithub.com\u002Fkospiotr\u002Fhello-js\u002Ftree\u002Fmaster\u002Fintern-unit-tests",[981],[984,10733,10734],{},"html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}",{"title":457,"searchDepth":471,"depth":471,"links":10736},[10737,10738,10742,10743,10747,10751,10752,10756,10757,10758,10759,10760,10761,10762],{"id":8020,"depth":471,"text":8021},{"id":8109,"depth":471,"text":8110,"children":10739},[10740,10741],{"id":8114,"depth":478,"text":8115},{"id":8124,"depth":478,"text":8125},{"id":8345,"depth":471,"text":8346},{"id":8478,"depth":471,"text":8479,"children":10744},[10745,10746],{"id":8485,"depth":478,"text":8486},{"id":8507,"depth":478,"text":8508},{"id":8607,"depth":471,"text":8608,"children":10748},[10749,10750],{"id":8611,"depth":478,"text":8612},{"id":8624,"depth":478,"text":8625},{"id":8646,"depth":471,"text":8647},{"id":8829,"depth":471,"text":8830,"children":10753},[10754,10755],{"id":8836,"depth":478,"text":8837},{"id":9078,"depth":478,"text":9079},{"id":9100,"depth":471,"text":9101},{"id":9159,"depth":471,"text":9141},{"id":9316,"depth":471,"text":9144},{"id":9755,"depth":471,"text":9147},{"id":9916,"depth":471,"text":9150},{"id":10171,"depth":471,"text":9153},{"id":10335,"depth":471,"text":9156},"2015-03-01","Unit tests in TDD with Intern",{"layout":993},"\u002Fblog\u002F2015-03-01-unit-tests-with-intern",{"title":8000,"description":10764},"2.blog\u002F2015-03-01-unit-tests-with-intern","vhHRarXM8a1t-1GrT97uBysbcZp1sapeu5tjBxJiQls",{"id":10771,"title":10772,"authors":409,"badge":409,"body":10773,"date":12787,"description":12788,"extension":991,"image":409,"meta":12789,"navigation":474,"path":12790,"seo":12791,"stem":12792,"__hash__":12793},"posts\u002F2.blog\u002F2015-03-03-end-to-end-tests-with-intern.md","REST end to end testing Node applications with Intern framework",{"type":423,"value":10774,"toc":12758},[10775,10777,10785,10787,10789,10791,10797,10801,10863,10865,10867,10872,10874,10878,10883,10887,11049,11055,11057,11059,11063,11125,11127,11132,11134,11139,11143,11171,11173,11175,11177,11179,11184,11186,11191,11193,11197,11267,11271,11276,11278,11280,11282,11287,11289,11291,11296,11298,11303,11307,11313,11318,11468,11470,11472,11474,11478,11687,11696,11698,11701,11706,11708,11714,11716,11718,11732,11734,11738,11741,11752,11756,11759,12576,12579,12585,12589,12593,12613,12617,12620,12623,12651,12659,12666,12670,12673,12684,12687,12704,12720,12727,12733,12737,12744,12746,12749,12755],[8004,10776,8007],{"id":8006},[426,10778,10779,10780,10784],{},"In the previous post [Testing Node applications with Intern framework](",[10781,10782],"binding",{"value":10783},"\u003C relref \"2015-03-01-unit-tests-with-intern\" >"," \"About Us\") I demostrated how to set up testing environment for unit tests with Intern and Grunt.\nToday I will show how to test REST endpoints with end to end tests in a speed of unit tests.",[426,10786,8016],{},[8018,10788,8021],{"id":8020},[426,10790,8024],{},[452,10792,10795],{"className":10793,"code":10794,"language":3262},[3260],"mkdir intern-end-to-end-tests\ncd intern-end-to-end-tests\n",[459,10796,10794],{"__ignoreMap":457},[426,10798,8033,10799,3095],{},[459,10800,8036],{},[452,10802,10804],{"className":8039,"code":10803,"language":8041,"meta":457,"style":457},"{\n  \"name\": \"intern-end-to-end-tests\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\"\n}\n",[459,10805,10806,10810,10829,10847,10859],{"__ignoreMap":457},[462,10807,10808],{"class":464,"line":465},[462,10809,7124],{"class":4190},[462,10811,10812,10814,10816,10818,10820,10822,10825,10827],{"class":464,"line":471},[462,10813,8052],{"class":4190},[462,10815,7358],{"class":3742},[462,10817,6886],{"class":4190},[462,10819,8059],{"class":6823},[462,10821,6886],{"class":4190},[462,10823,10824],{"class":3742},"intern-end-to-end-tests",[462,10826,6886],{"class":4190},[462,10828,7143],{"class":4190},[462,10830,10831,10833,10835,10837,10839,10841,10843,10845],{"class":464,"line":478},[462,10832,8052],{"class":4190},[462,10834,8075],{"class":3742},[462,10836,6886],{"class":4190},[462,10838,8059],{"class":6823},[462,10840,6886],{"class":4190},[462,10842,8084],{"class":3742},[462,10844,6886],{"class":4190},[462,10846,7143],{"class":4190},[462,10848,10849,10851,10853,10855,10857],{"class":464,"line":484},[462,10850,8052],{"class":4190},[462,10852,8095],{"class":3742},[462,10854,6886],{"class":4190},[462,10856,8059],{"class":6823},[462,10858,8102],{"class":4190},[462,10860,10861],{"class":464,"line":489},[462,10862,811],{"class":4190},[8018,10864,8110],{"id":8109},[8112,10866,8115],{"id":8114},[452,10868,10870],{"className":10869,"code":8119,"language":3262},[3260],[459,10871,8119],{"__ignoreMap":457},[8112,10873,8125],{"id":8124},[426,10875,8128,10876,8132],{},[459,10877,8131],{},[452,10879,10881],{"className":10880,"code":8136,"language":3262},[3260],[459,10882,8136],{"__ignoreMap":457},[426,10884,8141,10885,3095],{},[459,10886,8144],{},[452,10888,10889],{"className":8039,"code":8147,"language":8041,"meta":457,"style":457},[459,10890,10891,10913,10927,10931,10963,10983,11011,11019,11039],{"__ignoreMap":457},[462,10892,10893,10895,10897,10899,10901,10903,10905,10907,10909,10911],{"class":464,"line":465},[462,10894,8154],{"class":6827},[462,10896,8157],{"class":4186},[462,10898,4191],{"class":4190},[462,10900,8162],{"class":4285},[462,10902,7121],{"class":4186},[462,10904,7140],{"class":4190},[462,10906,8169],{"class":3742},[462,10908,7140],{"class":4190},[462,10910,7277],{"class":4186},[462,10912,6428],{"class":4190},[462,10914,10915,10917,10919,10921,10923,10925],{"class":464,"line":471},[462,10916,8154],{"class":6827},[462,10918,8182],{"class":4186},[462,10920,4191],{"class":4190},[462,10922,8187],{"class":4285},[462,10924,7172],{"class":4186},[462,10926,6428],{"class":4190},[462,10928,10929],{"class":464,"line":478},[462,10930,475],{"emptyLinePlaceholder":474},[462,10932,10933,10935,10937,10939,10941,10943,10945,10947,10949,10951,10953,10955,10957,10959,10961],{"class":464,"line":484},[462,10934,7155],{"class":4186},[462,10936,2762],{"class":4190},[462,10938,8204],{"class":4285},[462,10940,7121],{"class":4186},[462,10942,7140],{"class":4190},[462,10944,8211],{"class":3742},[462,10946,7140],{"class":4190},[462,10948,7196],{"class":4190},[462,10950,7169],{"class":6827},[462,10952,8220],{"class":4190},[462,10954,8224],{"class":8223},[462,10956,7196],{"class":4190},[462,10958,8229],{"class":8223},[462,10960,7277],{"class":4190},[462,10962,6415],{"class":4190},[462,10964,10965,10967,10969,10971,10973,10975,10977,10979,10981],{"class":464,"line":489},[462,10966,8238],{"class":4186},[462,10968,2762],{"class":4190},[462,10970,8243],{"class":4285},[462,10972,7121],{"class":6823},[462,10974,7140],{"class":4190},[462,10976,8250],{"class":3742},[462,10978,7140],{"class":4190},[462,10980,7277],{"class":6823},[462,10982,6428],{"class":4190},[462,10984,10985,10987,10989,10991,10993,10995,10997,10999,11001,11003,11005,11007,11009],{"class":464,"line":495},[462,10986,8261],{"class":4186},[462,10988,2762],{"class":4190},[462,10990,8266],{"class":4285},[462,10992,7121],{"class":6823},[462,10994,8271],{"class":4190},[462,10996,8274],{"class":6823},[462,10998,3095],{"class":4190},[462,11000,7134],{"class":4190},[462,11002,8281],{"class":3742},[462,11004,7140],{"class":4190},[462,11006,7289],{"class":4190},[462,11008,7277],{"class":6823},[462,11010,6428],{"class":4190},[462,11012,11013,11015,11017],{"class":464,"line":501},[462,11014,7289],{"class":4190},[462,11016,7277],{"class":4186},[462,11018,6428],{"class":4190},[462,11020,11021,11023,11025,11027,11029,11031,11033,11035,11037],{"class":464,"line":506},[462,11022,8302],{"class":4186},[462,11024,2762],{"class":4190},[462,11026,8243],{"class":4285},[462,11028,7121],{"class":4186},[462,11030,7140],{"class":4190},[462,11032,8313],{"class":3742},[462,11034,7140],{"class":4190},[462,11036,7277],{"class":4186},[462,11038,6428],{"class":4190},[462,11040,11041,11043,11045,11047],{"class":464,"line":512},[462,11042,8324],{"class":4190},[462,11044,8327],{"class":4190},[462,11046,8330],{"class":4186},[462,11048,6428],{"class":4190},[426,11050,8335,11051,8338,11053,8342],{},[459,11052,8211],{},[459,11054,8341],{},[8018,11056,8346],{"id":8345},[426,11058,8349],{},[426,11060,8141,11061,3095],{},[459,11062,8354],{},[452,11064,11065],{"className":8039,"code":8357,"language":8041,"meta":457,"style":457},[459,11066,11067,11089,11105],{"__ignoreMap":457},[462,11068,11069,11071,11073,11075,11077,11079,11081,11083,11085,11087],{"class":464,"line":465},[462,11070,8154],{"class":6827},[462,11072,8182],{"class":4186},[462,11074,4191],{"class":4190},[462,11076,8162],{"class":4285},[462,11078,7121],{"class":4186},[462,11080,7140],{"class":4190},[462,11082,8376],{"class":3742},[462,11084,7140],{"class":4190},[462,11086,7277],{"class":4186},[462,11088,6428],{"class":4190},[462,11090,11091,11093,11095,11097,11099,11101,11103],{"class":464,"line":471},[462,11092,7155],{"class":4186},[462,11094,2762],{"class":4190},[462,11096,8391],{"class":4285},[462,11098,7121],{"class":4186},[462,11100,8396],{"class":5513},[462,11102,7277],{"class":4186},[462,11104,6428],{"class":4190},[462,11106,11107,11109,11111,11113,11115,11117,11119,11121,11123],{"class":464,"line":478},[462,11108,8302],{"class":4186},[462,11110,2762],{"class":4190},[462,11112,8243],{"class":4285},[462,11114,7121],{"class":4186},[462,11116,7140],{"class":4190},[462,11118,8415],{"class":3742},[462,11120,7140],{"class":4190},[462,11122,7277],{"class":4186},[462,11124,6428],{"class":4190},[426,11126,8424],{},[452,11128,11130],{"className":11129,"code":8428,"language":3262},[3260],[459,11131,8428],{"__ignoreMap":457},[426,11133,8433],{},[452,11135,11137],{"className":11136,"code":8437,"language":3262},[3260],[459,11138,8437],{"__ignoreMap":457},[426,11140,8442,11141,8446],{},[459,11142,8445],{},[452,11144,11145],{"className":8039,"code":8449,"language":8041,"meta":457,"style":457},[459,11146,11147,11151,11167],{"__ignoreMap":457},[462,11148,11149],{"class":464,"line":465},[462,11150,7124],{"class":4190},[462,11152,11153,11155,11157,11159,11161,11163,11165],{"class":464,"line":471},[462,11154,6886],{"class":4190},[462,11156,8274],{"class":3742},[462,11158,6886],{"class":4190},[462,11160,8059],{"class":6823},[462,11162,6886],{"class":4190},[462,11164,8281],{"class":3742},[462,11166,7550],{"class":4190},[462,11168,11169],{"class":464,"line":478},[462,11170,811],{"class":4190},[8018,11172,8479],{"id":8478},[426,11174,8482],{},[8112,11176,8486],{"id":8485},[426,11178,8489],{},[452,11180,11182],{"className":11181,"code":8493,"language":3262},[3260],[459,11183,8493],{"__ignoreMap":457},[426,11185,8498],{},[452,11187,11189],{"className":11188,"code":8502,"language":3262},[3260],[459,11190,8502],{"__ignoreMap":457},[8112,11192,8508],{"id":8507},[426,11194,8511,11195,3095],{},[459,11196,8514],{},[452,11198,11199],{"className":8039,"code":8517,"language":8041,"meta":457,"style":457},[459,11200,11201,11217,11229,11237,11241,11263],{"__ignoreMap":457},[462,11202,11203,11205,11207,11209,11211,11213,11215],{"class":464,"line":465},[462,11204,8324],{"class":4190},[462,11206,8327],{"class":4190},[462,11208,7169],{"class":6827},[462,11210,8220],{"class":4190},[462,11212,8532],{"class":8223},[462,11214,7277],{"class":4190},[462,11216,6415],{"class":4190},[462,11218,11219,11221,11223,11225,11227],{"class":464,"line":471},[462,11220,8541],{"class":4186},[462,11222,2762],{"class":4190},[462,11224,8546],{"class":4285},[462,11226,7121],{"class":6823},[462,11228,7124],{"class":4190},[462,11230,11231,11233,11235],{"class":464,"line":478},[462,11232,7274],{"class":4190},[462,11234,7277],{"class":6823},[462,11236,6428],{"class":4190},[462,11238,11239],{"class":464,"line":484},[462,11240,475],{"emptyLinePlaceholder":474},[462,11242,11243,11245,11247,11249,11251,11253,11255,11257,11259,11261],{"class":464,"line":489},[462,11244,8541],{"class":4186},[462,11246,2762],{"class":4190},[462,11248,8571],{"class":4285},[462,11250,7121],{"class":6823},[462,11252,7140],{"class":4190},[462,11254,8578],{"class":3742},[462,11256,7140],{"class":4190},[462,11258,7196],{"class":4190},[462,11260,8585],{"class":6823},[462,11262,6428],{"class":4190},[462,11264,11265],{"class":464,"line":495},[462,11266,8592],{"class":4190},[426,11268,8595,11269,8598],{},[459,11270,8532],{},[452,11272,11274],{"className":11273,"code":8602,"language":3262},[3260],[459,11275,8602],{"__ignoreMap":457},[8018,11277,8608],{"id":8607},[8112,11279,8612],{"id":8611},[426,11281,8615],{},[452,11283,11285],{"className":11284,"code":8619,"language":3262},[3260],[459,11286,8619],{"__ignoreMap":457},[8112,11288,8625],{"id":8624},[426,11290,8628],{},[452,11292,11294],{"className":11293,"code":8632,"language":3262},[3260],[459,11295,8632],{"__ignoreMap":457},[426,11297,8637],{},[452,11299,11301],{"className":11300,"code":8641,"language":3262},[3260],[459,11302,8641],{"__ignoreMap":457},[8018,11304,11306],{"id":11305},"create-first-test","Create first test",[452,11308,11311],{"className":11309,"code":11310,"language":3262},[3260],"mkdir test\u002Fe2e\n",[459,11312,11310],{"__ignoreMap":457},[426,11314,8656,11315,3095],{},[459,11316,11317],{},"test\u002Fe2e\u002FtestRestTest.js",[452,11319,11320],{"className":8039,"code":8662,"language":8041,"meta":457,"style":457},[459,11321,11322,11338,11360,11382,11386,11390,11398,11414,11448,11452,11460],{"__ignoreMap":457},[462,11323,11324,11326,11328,11330,11332,11334,11336],{"class":464,"line":465},[462,11325,8669],{"class":4285},[462,11327,7121],{"class":4186},[462,11329,8674],{"class":6827},[462,11331,8220],{"class":4190},[462,11333,8679],{"class":8223},[462,11335,7277],{"class":4190},[462,11337,6415],{"class":4190},[462,11339,11340,11342,11344,11346,11348,11350,11352,11354,11356,11358],{"class":464,"line":471},[462,11341,8688],{"class":6827},[462,11343,8691],{"class":4186},[462,11345,8327],{"class":4190},[462,11347,8162],{"class":4285},[462,11349,7121],{"class":6823},[462,11351,7140],{"class":4190},[462,11353,8702],{"class":3742},[462,11355,7140],{"class":4190},[462,11357,7277],{"class":6823},[462,11359,6428],{"class":4190},[462,11361,11362,11364,11366,11368,11370,11372,11374,11376,11378,11380],{"class":464,"line":478},[462,11363,8688],{"class":6827},[462,11365,8715],{"class":4186},[462,11367,8327],{"class":4190},[462,11369,8162],{"class":4285},[462,11371,7121],{"class":6823},[462,11373,7140],{"class":4190},[462,11375,8726],{"class":3742},[462,11377,7140],{"class":4190},[462,11379,7277],{"class":6823},[462,11381,6428],{"class":4190},[462,11383,11384],{"class":464,"line":484},[462,11385,475],{"emptyLinePlaceholder":474},[462,11387,11388],{"class":464,"line":489},[462,11389,475],{"emptyLinePlaceholder":474},[462,11391,11392,11394,11396],{"class":464,"line":495},[462,11393,8745],{"class":4285},[462,11395,7121],{"class":6823},[462,11397,7124],{"class":4190},[462,11399,11400,11402,11404,11406,11408,11410,11412],{"class":464,"line":501},[462,11401,8754],{"class":4190},[462,11403,8757],{"class":6823},[462,11405,7140],{"class":4190},[462,11407,3095],{"class":4190},[462,11409,7169],{"class":6827},[462,11411,8766],{"class":4190},[462,11413,6415],{"class":4190},[462,11415,11416,11418,11420,11422,11424,11426,11428,11430,11432,11434,11436,11438,11440,11442,11444,11446],{"class":464,"line":506},[462,11417,8773],{"class":4285},[462,11419,7121],{"class":6823},[462,11421,6886],{"class":4190},[462,11423,8780],{"class":3742},[462,11425,6886],{"class":4190},[462,11427,7277],{"class":6823},[462,11429,2762],{"class":4190},[462,11431,8789],{"class":4186},[462,11433,2762],{"class":4190},[462,11435,8794],{"class":4285},[462,11437,7121],{"class":6823},[462,11439,7140],{"class":4190},[462,11441,8780],{"class":3742},[462,11443,7140],{"class":4190},[462,11445,7277],{"class":6823},[462,11447,6428],{"class":4190},[462,11449,11450],{"class":464,"line":512},[462,11451,1077],{"class":4190},[462,11453,11454,11456,11458],{"class":464,"line":518},[462,11455,7274],{"class":4190},[462,11457,7277],{"class":6823},[462,11459,6428],{"class":4190},[462,11461,11462,11464,11466],{"class":464,"line":524},[462,11463,7289],{"class":4190},[462,11465,7277],{"class":4186},[462,11467,6428],{"class":4190},[8018,11469,8830],{"id":8829},[426,11471,8833],{},[8112,11473,8837],{"id":8836},[426,11475,8840,11476,3095],{},[459,11477,8514],{},[452,11479,11481],{"className":8039,"code":11480,"language":8041,"meta":457,"style":457},"module.exports = function (grunt) {\n\n    grunt.initConfig({\n        intern: {\n            e2e_testing: {\n                options: {\n                    config: 'test\u002Fintern-config',\n                    suites: ['test\u002Fe2e\u002FtestRestTest']\n                }\n            }\n        }\n    });\n\n    grunt.loadNpmTasks('intern');\n\n    grunt.registerTask('default', ['test']);\n    grunt.registerTask('test', ['intern']);\n\n};\n\n",[459,11482,11483,11499,11503,11515,11523,11532,11540,11554,11571,11575,11579,11583,11591,11595,11615,11619,11649,11679,11683],{"__ignoreMap":457},[462,11484,11485,11487,11489,11491,11493,11495,11497],{"class":464,"line":465},[462,11486,8324],{"class":4190},[462,11488,8327],{"class":4190},[462,11490,7169],{"class":6827},[462,11492,8220],{"class":4190},[462,11494,8532],{"class":8223},[462,11496,7277],{"class":4190},[462,11498,6415],{"class":4190},[462,11500,11501],{"class":464,"line":471},[462,11502,475],{"emptyLinePlaceholder":474},[462,11504,11505,11507,11509,11511,11513],{"class":464,"line":478},[462,11506,8541],{"class":4186},[462,11508,2762],{"class":4190},[462,11510,8546],{"class":4285},[462,11512,7121],{"class":6823},[462,11514,7124],{"class":4190},[462,11516,11517,11519,11521],{"class":464,"line":484},[462,11518,8884],{"class":6823},[462,11520,3095],{"class":4190},[462,11522,6415],{"class":4190},[462,11524,11525,11528,11530],{"class":464,"line":489},[462,11526,11527],{"class":6823},"            e2e_testing",[462,11529,3095],{"class":4190},[462,11531,6415],{"class":4190},[462,11533,11534,11536,11538],{"class":464,"line":495},[462,11535,8902],{"class":6823},[462,11537,3095],{"class":4190},[462,11539,6415],{"class":4190},[462,11541,11542,11544,11546,11548,11550,11552],{"class":464,"line":501},[462,11543,8911],{"class":6823},[462,11545,3095],{"class":4190},[462,11547,7134],{"class":4190},[462,11549,8918],{"class":3742},[462,11551,7140],{"class":4190},[462,11553,7143],{"class":4190},[462,11555,11556,11558,11560,11562,11564,11567,11569],{"class":464,"line":506},[462,11557,8927],{"class":6823},[462,11559,3095],{"class":4190},[462,11561,8932],{"class":6823},[462,11563,7140],{"class":4190},[462,11565,11566],{"class":3742},"test\u002Fe2e\u002FtestRestTest",[462,11568,7140],{"class":4190},[462,11570,8942],{"class":6823},[462,11572,11573],{"class":464,"line":512},[462,11574,2696],{"class":4190},[462,11576,11577],{"class":464,"line":518},[462,11578,777],{"class":4190},[462,11580,11581],{"class":464,"line":524},[462,11582,1077],{"class":4190},[462,11584,11585,11587,11589],{"class":464,"line":530},[462,11586,7274],{"class":4190},[462,11588,7277],{"class":6823},[462,11590,6428],{"class":4190},[462,11592,11593],{"class":464,"line":536},[462,11594,475],{"emptyLinePlaceholder":474},[462,11596,11597,11599,11601,11603,11605,11607,11609,11611,11613],{"class":464,"line":542},[462,11598,8541],{"class":4186},[462,11600,2762],{"class":4190},[462,11602,8975],{"class":4285},[462,11604,7121],{"class":6823},[462,11606,7140],{"class":4190},[462,11608,8982],{"class":3742},[462,11610,7140],{"class":4190},[462,11612,7277],{"class":6823},[462,11614,6428],{"class":4190},[462,11616,11617],{"class":464,"line":547},[462,11618,475],{"emptyLinePlaceholder":474},[462,11620,11621,11623,11625,11627,11629,11631,11633,11635,11637,11639,11641,11643,11645,11647],{"class":464,"line":553},[462,11622,8541],{"class":4186},[462,11624,2762],{"class":4190},[462,11626,8571],{"class":4285},[462,11628,7121],{"class":6823},[462,11630,7140],{"class":4190},[462,11632,8578],{"class":3742},[462,11634,7140],{"class":4190},[462,11636,7196],{"class":4190},[462,11638,8932],{"class":6823},[462,11640,7140],{"class":4190},[462,11642,9017],{"class":3742},[462,11644,7140],{"class":4190},[462,11646,9022],{"class":6823},[462,11648,6428],{"class":4190},[462,11650,11651,11653,11655,11657,11659,11661,11663,11665,11667,11669,11671,11673,11675,11677],{"class":464,"line":558},[462,11652,8541],{"class":4186},[462,11654,2762],{"class":4190},[462,11656,8571],{"class":4285},[462,11658,7121],{"class":6823},[462,11660,7140],{"class":4190},[462,11662,9017],{"class":3742},[462,11664,7140],{"class":4190},[462,11666,7196],{"class":4190},[462,11668,8932],{"class":6823},[462,11670,7140],{"class":4190},[462,11672,8982],{"class":3742},[462,11674,7140],{"class":4190},[462,11676,9022],{"class":6823},[462,11678,6428],{"class":4190},[462,11680,11681],{"class":464,"line":564},[462,11682,475],{"emptyLinePlaceholder":474},[462,11684,11685],{"class":464,"line":693},[462,11686,8592],{"class":4190},[426,11688,9065,11689,9068,11691,9072,11694,9075],{},[459,11690,8982],{},[459,11692,11693],{},"intern:e2e_testing",[459,11695,9017],{},[8112,11697,9079],{"id":9078},[426,11699,11700],{},"Lets execute test task:",[452,11702,11704],{"className":11703,"code":9086,"language":3262},[3260],[459,11705,9086],{"__ignoreMap":457},[426,11707,9091],{},[452,11709,11712],{"className":11710,"code":11711,"language":3262},[3260],"Running \"intern:e2e_testing\" (intern) task\n>> PASS: main -  -  strings (0ms)\n>> 0\u002F1 tests failed\n>> 0\u002F1 tests failed\n",[459,11713,11711],{"__ignoreMap":457},[8018,11715,9101],{"id":9100},[426,11717,9104],{},[439,11719,11720,11724,11726,11728,11730],{},[442,11721,9109,11722,9112],{},[459,11723,8211],{},[442,11725,9115],{},[442,11727,9118],{},[442,11729,9121],{},[442,11731,9124],{},[426,11733,9127],{},[8004,11735,11737],{"id":11736},"create-real-end-to-end-test","Create real end to end test",[426,11739,11740],{},"At this point we have configured infrastructure that allows now to focus on creating real end to end test.\nThe sequence of the testing is:",[6733,11742,11743,11746,11749],{},[442,11744,11745],{},"Prepare Express application and host it on the local server",[442,11747,11748],{},"Execute all suite test cases which will call local REST endpoint and ensure they are valid",[442,11750,11751],{},"Shut down server",[8018,11753,11755],{"id":11754},"full-example","Full example",[426,11757,11758],{},"Full example of the test lokks as below:",[452,11760,11762],{"className":8039,"code":11761,"language":8041,"meta":457,"style":457},"define(function (require) {\n    var suite = require('intern!object'),\n        app = require('intern\u002Fdojo\u002Fnode!..\u002F..\u002Fsrc\u002Fapp'),\n        chai = require('intern\u002Fdojo\u002Fnode!chai'), \u002F\u002Fdellivers promieses implementation used in setup method\n        expect = chai.expect,\n        chaiHttp = require('intern\u002Fdojo\u002Fnode!chai-http'), \u002F\u002Fdellivers promieses implementation used in setup method\n        q = require('intern\u002Fdojo\u002Fnode!q'), \u002F\u002Fdellivers promieses implementation used in setup method\n        portfinder = require('intern\u002Fdojo\u002Fnode!portfinder'); \u002F\u002Fdellivers promieses implementation used in setup method\n\n    var me = this;\n    var api = function () {\n        return chai.request('http:\u002F\u002Flocalhost:' + me.port);\n    }\n\n    suite({\n        'setup': function () {\n            chai.use(chaiHttp); \u002F\u002Fconfigure chai with chaiHttp\n            chai.request.addPromises(q.Promise); \u002F\u002Fconfigure promise for chaiHttp\n\n            var deferred = q.defer();\n            portfinder.getPort(function (err, port) {\n                me.port = port;\n                me.server = app.listen(me.port, function () {\n                    console.log('server is running on port %j', me.port);\n                    deferred.resolve();\n                });\n            });\n            return deferred.promise;\n\n        },\n        'teardown': function () {\n            me.server.close();\n        },\n        'shoud test return status ok json': function () {\n            return api()                                        \u002F\u002Fprepare url\n                .get('\u002Ftest')                                   \u002F\u002Fmake a call\n                .then(function (res) {                          \u002F\u002Freturn call result\n                    expect(res.body).to.eql({status: 'ok'});    \u002F\u002Fmake assertions with chai\n                });\n        },\n        'another test': function () {\n            return api()\n                .get('\u002Ftest')\n                .then(function (res) {\n                    expect(res.body).to.eql({status: 'ok'});\n                });\n        }\n    });\n});\n\n",[459,11763,11764,11780,11802,11824,11849,11866,11890,11914,11938,11942,11954,11969,12003,12007,12011,12019,12036,12058,12088,12092,12114,12142,12157,12191,12221,12235,12244,12253,12267,12271,12275,12292,12310,12314,12331,12343,12364,12387,12434,12442,12446,12463,12472,12488,12506,12548,12556,12560,12568],{"__ignoreMap":457},[462,11765,11766,11768,11770,11772,11774,11776,11778],{"class":464,"line":465},[462,11767,8669],{"class":4285},[462,11769,7121],{"class":4186},[462,11771,8674],{"class":6827},[462,11773,8220],{"class":4190},[462,11775,8679],{"class":8223},[462,11777,7277],{"class":4190},[462,11779,6415],{"class":4190},[462,11781,11782,11784,11786,11788,11790,11792,11794,11796,11798,11800],{"class":464,"line":471},[462,11783,8688],{"class":6827},[462,11785,8691],{"class":4186},[462,11787,8327],{"class":4190},[462,11789,8162],{"class":4285},[462,11791,7121],{"class":6823},[462,11793,7140],{"class":4190},[462,11795,8702],{"class":3742},[462,11797,7140],{"class":4190},[462,11799,7277],{"class":6823},[462,11801,7143],{"class":4190},[462,11803,11804,11807,11809,11811,11813,11815,11818,11820,11822],{"class":464,"line":478},[462,11805,11806],{"class":4186},"        app",[462,11808,8327],{"class":4190},[462,11810,8162],{"class":4285},[462,11812,7121],{"class":6823},[462,11814,7140],{"class":4190},[462,11816,11817],{"class":3742},"intern\u002Fdojo\u002Fnode!..\u002F..\u002Fsrc\u002Fapp",[462,11819,7140],{"class":4190},[462,11821,7277],{"class":6823},[462,11823,7143],{"class":4190},[462,11825,11826,11829,11831,11833,11835,11837,11840,11842,11844,11846],{"class":464,"line":484},[462,11827,11828],{"class":4186},"        chai",[462,11830,8327],{"class":4190},[462,11832,8162],{"class":4285},[462,11834,7121],{"class":6823},[462,11836,7140],{"class":4190},[462,11838,11839],{"class":3742},"intern\u002Fdojo\u002Fnode!chai",[462,11841,7140],{"class":4190},[462,11843,7277],{"class":6823},[462,11845,7196],{"class":4190},[462,11847,11848],{"class":6933}," \u002F\u002Fdellivers promieses implementation used in setup method\n",[462,11850,11851,11854,11856,11859,11861,11864],{"class":464,"line":489},[462,11852,11853],{"class":4186},"        expect",[462,11855,8327],{"class":4190},[462,11857,11858],{"class":4186}," chai",[462,11860,2762],{"class":4190},[462,11862,11863],{"class":4186},"expect",[462,11865,7143],{"class":4190},[462,11867,11868,11871,11873,11875,11877,11879,11882,11884,11886,11888],{"class":464,"line":495},[462,11869,11870],{"class":4186},"        chaiHttp",[462,11872,8327],{"class":4190},[462,11874,8162],{"class":4285},[462,11876,7121],{"class":6823},[462,11878,7140],{"class":4190},[462,11880,11881],{"class":3742},"intern\u002Fdojo\u002Fnode!chai-http",[462,11883,7140],{"class":4190},[462,11885,7277],{"class":6823},[462,11887,7196],{"class":4190},[462,11889,11848],{"class":6933},[462,11891,11892,11895,11897,11899,11901,11903,11906,11908,11910,11912],{"class":464,"line":501},[462,11893,11894],{"class":4186},"        q",[462,11896,8327],{"class":4190},[462,11898,8162],{"class":4285},[462,11900,7121],{"class":6823},[462,11902,7140],{"class":4190},[462,11904,11905],{"class":3742},"intern\u002Fdojo\u002Fnode!q",[462,11907,7140],{"class":4190},[462,11909,7277],{"class":6823},[462,11911,7196],{"class":4190},[462,11913,11848],{"class":6933},[462,11915,11916,11919,11921,11923,11925,11927,11930,11932,11934,11936],{"class":464,"line":506},[462,11917,11918],{"class":4186},"        portfinder",[462,11920,8327],{"class":4190},[462,11922,8162],{"class":4285},[462,11924,7121],{"class":6823},[462,11926,7140],{"class":4190},[462,11928,11929],{"class":3742},"intern\u002Fdojo\u002Fnode!portfinder",[462,11931,7140],{"class":4190},[462,11933,7277],{"class":6823},[462,11935,6374],{"class":4190},[462,11937,11848],{"class":6933},[462,11939,11940],{"class":464,"line":512},[462,11941,475],{"emptyLinePlaceholder":474},[462,11943,11944,11946,11949,11951],{"class":464,"line":518},[462,11945,8688],{"class":6827},[462,11947,11948],{"class":4186}," me",[462,11950,8327],{"class":4190},[462,11952,11953],{"class":4190}," this;\n",[462,11955,11956,11958,11961,11963,11965,11967],{"class":464,"line":524},[462,11957,8688],{"class":6827},[462,11959,11960],{"class":4186}," api",[462,11962,8327],{"class":4190},[462,11964,7169],{"class":6827},[462,11966,8766],{"class":4190},[462,11968,6415],{"class":4190},[462,11970,11971,11973,11975,11977,11980,11982,11984,11987,11989,11992,11994,11996,11999,12001],{"class":464,"line":530},[462,11972,9210],{"class":9209},[462,11974,11858],{"class":4186},[462,11976,2762],{"class":4190},[462,11978,11979],{"class":4285},"request",[462,11981,7121],{"class":6823},[462,11983,7140],{"class":4190},[462,11985,11986],{"class":3742},"http:\u002F\u002Flocalhost:",[462,11988,7140],{"class":4190},[462,11990,11991],{"class":4190}," +",[462,11993,11948],{"class":4186},[462,11995,2762],{"class":4190},[462,11997,11998],{"class":4186},"port",[462,12000,7277],{"class":6823},[462,12002,6428],{"class":4190},[462,12004,12005],{"class":464,"line":536},[462,12006,702],{"class":4190},[462,12008,12009],{"class":464,"line":542},[462,12010,475],{"emptyLinePlaceholder":474},[462,12012,12013,12015,12017],{"class":464,"line":547},[462,12014,8745],{"class":4285},[462,12016,7121],{"class":6823},[462,12018,7124],{"class":4190},[462,12020,12021,12023,12026,12028,12030,12032,12034],{"class":464,"line":553},[462,12022,8754],{"class":4190},[462,12024,12025],{"class":6823},"setup",[462,12027,7140],{"class":4190},[462,12029,3095],{"class":4190},[462,12031,7169],{"class":6827},[462,12033,8766],{"class":4190},[462,12035,6415],{"class":4190},[462,12037,12038,12041,12043,12046,12048,12051,12053,12055],{"class":464,"line":558},[462,12039,12040],{"class":4186},"            chai",[462,12042,2762],{"class":4190},[462,12044,12045],{"class":4285},"use",[462,12047,7121],{"class":6823},[462,12049,12050],{"class":4186},"chaiHttp",[462,12052,7277],{"class":6823},[462,12054,6374],{"class":4190},[462,12056,12057],{"class":6933}," \u002F\u002Fconfigure chai with chaiHttp\n",[462,12059,12060,12062,12064,12066,12068,12071,12073,12076,12078,12081,12083,12085],{"class":464,"line":564},[462,12061,12040],{"class":4186},[462,12063,2762],{"class":4190},[462,12065,11979],{"class":4186},[462,12067,2762],{"class":4190},[462,12069,12070],{"class":4285},"addPromises",[462,12072,7121],{"class":6823},[462,12074,12075],{"class":4186},"q",[462,12077,2762],{"class":4190},[462,12079,12080],{"class":4186},"Promise",[462,12082,7277],{"class":6823},[462,12084,6374],{"class":4190},[462,12086,12087],{"class":6933}," \u002F\u002Fconfigure promise for chaiHttp\n",[462,12089,12090],{"class":464,"line":693},[462,12091,475],{"emptyLinePlaceholder":474},[462,12093,12094,12097,12100,12102,12105,12107,12110,12112],{"class":464,"line":699},[462,12095,12096],{"class":6827},"            var",[462,12098,12099],{"class":4186}," deferred",[462,12101,8327],{"class":4190},[462,12103,12104],{"class":4186}," q",[462,12106,2762],{"class":4190},[462,12108,12109],{"class":4285},"defer",[462,12111,7172],{"class":6823},[462,12113,6428],{"class":4190},[462,12115,12116,12119,12121,12124,12126,12128,12130,12133,12135,12138,12140],{"class":464,"line":705},[462,12117,12118],{"class":4186},"            portfinder",[462,12120,2762],{"class":4190},[462,12122,12123],{"class":4285},"getPort",[462,12125,7121],{"class":6823},[462,12127,8674],{"class":6827},[462,12129,8220],{"class":4190},[462,12131,12132],{"class":8223},"err",[462,12134,7196],{"class":4190},[462,12136,12137],{"class":8223}," port",[462,12139,7277],{"class":4190},[462,12141,6415],{"class":4190},[462,12143,12144,12147,12149,12151,12153,12155],{"class":464,"line":710},[462,12145,12146],{"class":4186},"                me",[462,12148,2762],{"class":4190},[462,12150,11998],{"class":4186},[462,12152,8327],{"class":4190},[462,12154,12137],{"class":4186},[462,12156,6428],{"class":4190},[462,12158,12159,12161,12163,12166,12168,12170,12172,12174,12176,12179,12181,12183,12185,12187,12189],{"class":464,"line":715},[462,12160,12146],{"class":4186},[462,12162,2762],{"class":4190},[462,12164,12165],{"class":4186},"server",[462,12167,8327],{"class":4190},[462,12169,8330],{"class":4186},[462,12171,2762],{"class":4190},[462,12173,8391],{"class":4285},[462,12175,7121],{"class":6823},[462,12177,12178],{"class":4186},"me",[462,12180,2762],{"class":4190},[462,12182,11998],{"class":4186},[462,12184,7196],{"class":4190},[462,12186,7169],{"class":6827},[462,12188,8766],{"class":4190},[462,12190,6415],{"class":4190},[462,12192,12193,12196,12198,12200,12202,12204,12207,12209,12211,12213,12215,12217,12219],{"class":464,"line":721},[462,12194,12195],{"class":4186},"                    console",[462,12197,2762],{"class":4190},[462,12199,8243],{"class":4285},[462,12201,7121],{"class":6823},[462,12203,7140],{"class":4190},[462,12205,12206],{"class":3742},"server is running on port %j",[462,12208,7140],{"class":4190},[462,12210,7196],{"class":4190},[462,12212,11948],{"class":4186},[462,12214,2762],{"class":4190},[462,12216,11998],{"class":4186},[462,12218,7277],{"class":6823},[462,12220,6428],{"class":4190},[462,12222,12223,12226,12228,12231,12233],{"class":464,"line":727},[462,12224,12225],{"class":4186},"                    deferred",[462,12227,2762],{"class":4190},[462,12229,12230],{"class":4285},"resolve",[462,12232,7172],{"class":6823},[462,12234,6428],{"class":4190},[462,12236,12237,12240,12242],{"class":464,"line":732},[462,12238,12239],{"class":4190},"                }",[462,12241,7277],{"class":6823},[462,12243,6428],{"class":4190},[462,12245,12246,12249,12251],{"class":464,"line":738},[462,12247,12248],{"class":4190},"            }",[462,12250,7277],{"class":6823},[462,12252,6428],{"class":4190},[462,12254,12255,12258,12260,12262,12265],{"class":464,"line":744},[462,12256,12257],{"class":9209},"            return",[462,12259,12099],{"class":4186},[462,12261,2762],{"class":4190},[462,12263,12264],{"class":4186},"promise",[462,12266,6428],{"class":4190},[462,12268,12269],{"class":464,"line":750},[462,12270,475],{"emptyLinePlaceholder":474},[462,12272,12273],{"class":464,"line":756},[462,12274,10081],{"class":4190},[462,12276,12277,12279,12282,12284,12286,12288,12290],{"class":464,"line":762},[462,12278,8754],{"class":4190},[462,12280,12281],{"class":6823},"teardown",[462,12283,7140],{"class":4190},[462,12285,3095],{"class":4190},[462,12287,7169],{"class":6827},[462,12289,8766],{"class":4190},[462,12291,6415],{"class":4190},[462,12293,12294,12297,12299,12301,12303,12306,12308],{"class":464,"line":768},[462,12295,12296],{"class":4186},"            me",[462,12298,2762],{"class":4190},[462,12300,12165],{"class":4186},[462,12302,2762],{"class":4190},[462,12304,12305],{"class":4285},"close",[462,12307,7172],{"class":6823},[462,12309,6428],{"class":4190},[462,12311,12312],{"class":464,"line":774},[462,12313,10081],{"class":4190},[462,12315,12316,12318,12321,12323,12325,12327,12329],{"class":464,"line":780},[462,12317,8754],{"class":4190},[462,12319,12320],{"class":6823},"shoud test return status ok json",[462,12322,7140],{"class":4190},[462,12324,3095],{"class":4190},[462,12326,7169],{"class":6827},[462,12328,8766],{"class":4190},[462,12330,6415],{"class":4190},[462,12332,12333,12335,12337,12340],{"class":464,"line":786},[462,12334,12257],{"class":9209},[462,12336,11960],{"class":4285},[462,12338,12339],{"class":6823},"()                                        ",[462,12341,12342],{"class":6933},"\u002F\u002Fprepare url\n",[462,12344,12345,12348,12350,12352,12354,12356,12358,12361],{"class":464,"line":791},[462,12346,12347],{"class":4190},"                .",[462,12349,8204],{"class":4285},[462,12351,7121],{"class":6823},[462,12353,7140],{"class":4190},[462,12355,8211],{"class":3742},[462,12357,7140],{"class":4190},[462,12359,12360],{"class":6823},")                                   ",[462,12362,12363],{"class":6933},"\u002F\u002Fmake a call\n",[462,12365,12366,12368,12371,12373,12375,12377,12380,12382,12384],{"class":464,"line":797},[462,12367,12347],{"class":4190},[462,12369,12370],{"class":4285},"then",[462,12372,7121],{"class":6823},[462,12374,8674],{"class":6827},[462,12376,8220],{"class":4190},[462,12378,12379],{"class":8223},"res",[462,12381,7277],{"class":4190},[462,12383,6358],{"class":4190},[462,12385,12386],{"class":6933},"                          \u002F\u002Freturn call result\n",[462,12388,12389,12392,12394,12396,12398,12400,12402,12404,12406,12408,12411,12413,12415,12417,12419,12421,12423,12425,12427,12429,12431],{"class":464,"line":803},[462,12390,12391],{"class":4285},"                    expect",[462,12393,7121],{"class":6823},[462,12395,12379],{"class":4186},[462,12397,2762],{"class":4190},[462,12399,7077],{"class":4186},[462,12401,7277],{"class":6823},[462,12403,2762],{"class":4190},[462,12405,8789],{"class":4186},[462,12407,2762],{"class":4190},[462,12409,12410],{"class":4285},"eql",[462,12412,7121],{"class":6823},[462,12414,8271],{"class":4190},[462,12416,8274],{"class":6823},[462,12418,3095],{"class":4190},[462,12420,7134],{"class":4190},[462,12422,8281],{"class":3742},[462,12424,7140],{"class":4190},[462,12426,7289],{"class":4190},[462,12428,7277],{"class":6823},[462,12430,6374],{"class":4190},[462,12432,12433],{"class":6933},"    \u002F\u002Fmake assertions with chai\n",[462,12435,12436,12438,12440],{"class":464,"line":808},[462,12437,12239],{"class":4190},[462,12439,7277],{"class":6823},[462,12441,6428],{"class":4190},[462,12443,12444],{"class":464,"line":2107},[462,12445,10081],{"class":4190},[462,12447,12448,12450,12453,12455,12457,12459,12461],{"class":464,"line":2112},[462,12449,8754],{"class":4190},[462,12451,12452],{"class":6823},"another test",[462,12454,7140],{"class":4190},[462,12456,3095],{"class":4190},[462,12458,7169],{"class":6827},[462,12460,8766],{"class":4190},[462,12462,6415],{"class":4190},[462,12464,12465,12467,12469],{"class":464,"line":2117},[462,12466,12257],{"class":9209},[462,12468,11960],{"class":4285},[462,12470,12471],{"class":6823},"()\n",[462,12473,12474,12476,12478,12480,12482,12484,12486],{"class":464,"line":2431},[462,12475,12347],{"class":4190},[462,12477,8204],{"class":4285},[462,12479,7121],{"class":6823},[462,12481,7140],{"class":4190},[462,12483,8211],{"class":3742},[462,12485,7140],{"class":4190},[462,12487,5435],{"class":6823},[462,12489,12490,12492,12494,12496,12498,12500,12502,12504],{"class":464,"line":2437},[462,12491,12347],{"class":4190},[462,12493,12370],{"class":4285},[462,12495,7121],{"class":6823},[462,12497,8674],{"class":6827},[462,12499,8220],{"class":4190},[462,12501,12379],{"class":8223},[462,12503,7277],{"class":4190},[462,12505,6415],{"class":4190},[462,12507,12508,12510,12512,12514,12516,12518,12520,12522,12524,12526,12528,12530,12532,12534,12536,12538,12540,12542,12544,12546],{"class":464,"line":2443},[462,12509,12391],{"class":4285},[462,12511,7121],{"class":6823},[462,12513,12379],{"class":4186},[462,12515,2762],{"class":4190},[462,12517,7077],{"class":4186},[462,12519,7277],{"class":6823},[462,12521,2762],{"class":4190},[462,12523,8789],{"class":4186},[462,12525,2762],{"class":4190},[462,12527,12410],{"class":4285},[462,12529,7121],{"class":6823},[462,12531,8271],{"class":4190},[462,12533,8274],{"class":6823},[462,12535,3095],{"class":4190},[462,12537,7134],{"class":4190},[462,12539,8281],{"class":3742},[462,12541,7140],{"class":4190},[462,12543,7289],{"class":4190},[462,12545,7277],{"class":6823},[462,12547,6428],{"class":4190},[462,12549,12550,12552,12554],{"class":464,"line":2448},[462,12551,12239],{"class":4190},[462,12553,7277],{"class":6823},[462,12555,6428],{"class":4190},[462,12557,12558],{"class":464,"line":4600},[462,12559,1077],{"class":4190},[462,12561,12562,12564,12566],{"class":464,"line":4605},[462,12563,7274],{"class":4190},[462,12565,7277],{"class":6823},[462,12567,6428],{"class":4190},[462,12569,12570,12572,12574],{"class":464,"line":4610},[462,12571,7289],{"class":4190},[462,12573,7277],{"class":4186},[462,12575,6428],{"class":4190},[426,12577,12578],{},"and it requires following dependencies:",[452,12580,12583],{"className":12581,"code":12582,"language":3262},[3260],"npm install chai chai-http q portfinder --save-dev\n",[459,12584,12582],{"__ignoreMap":457},[8018,12586,12588],{"id":12587},"explanation","Explanation",[8112,12590,12592],{"id":12591},"dependencies","Dependencies",[439,12594,12595,12601,12607,12610],{},[442,12596,12597,12598],{},"chai - is an assertion library that allows to ensure some preconditions, like ",[459,12599,12600],{},"request body must equals json: {status: 'ok'}",[442,12602,12603,12604],{},"chai-http - is a plugin for chai that allows to construct and handles HTTP calls, for example making GET call to ",[977,12605,8445],{"href":8445,"rel":12606},[981],[442,12608,12609],{},"q - is a library that allows working with promises in NodeJS application, which allows to work with asynhronous tests",[442,12611,12612],{},"portfinder - is a simple tool to find an open port or domain socket on the current machine",[8112,12614,12616],{"id":12615},"lifecycle","Lifecycle",[426,12618,12619],{},"When Intern tests are executed, the test system follows a specific lifecycle:",[426,12621,12622],{},"For each registered root suite:",[439,12624,12625,12631,12647],{},[442,12626,12627,12628,12630],{},"The ",[459,12629,12025],{}," method of the suite is called, if it exists",[442,12632,12633,12634],{},"For each test within the suite:\n",[439,12635,12636,12642],{},[442,12637,12627,12638,12641],{},[459,12639,12640],{},"beforeEach"," method of the suite is called, if it exists\n*  The test function is called",[442,12643,12627,12644,12630],{},[459,12645,12646],{},"afterEach",[442,12648,12627,12649,12630],{},[459,12650,12281],{},[426,12652,12653,12654,12656,12657,2762],{},"In order to start server once for all tests and close it on the end of the suite we will start it in ",[459,12655,12025],{}," method and shut it down in ",[459,12658,12281],{},[426,12660,12661,12662],{},"Source: ",[977,12663,12664],{"href":12664,"rel":12665},"https:\u002F\u002Ftheintern.github.io\u002Fintern\u002F#test-lifecycle",[981],[8112,12667,12669],{"id":12668},"asynchronous-tests","Asynchronous tests",[426,12671,12672],{},"Most of the testing will be asynchronous, for example all HTTP calls are asynchronous, server will start in asynchronous and also finding free port is asynchronous. Intern support two mechanisms of handling asynchronous tests:",[439,12674,12675,12681],{},[442,12676,12677,12678],{},"Using ",[459,12679,12680],{},"this.async()",[442,12682,12683],{},"Promises",[426,12685,12686],{},"First method is very simple, but doesn't work in lifecycle methods, and looks disgusting. This way is documented very well in the Intern guide so I won't go this way.\nThe benefits with promises are:",[439,12688,12689,12695,12698,12701],{},[442,12690,12691,12692,12694],{},"They are supported in tests and also in lifecycle methods. If simple tests doesn't require to handle asynchronous methods in for example ",[459,12693,12025],{}," method you don't need go with promises. As we will start server we need to stick with promises.",[442,12696,12697],{},"They looks much more better, and I mean they are more easy to write so also maintain.",[442,12699,12700],{},"Soon they will become standard",[442,12702,12703],{},"Easy to use in Intern test",[426,12705,12706,12707,12709,12710,12712,12713,12716,12717,12719],{},"Promise is not supported out of the box, and we need to deliver it with one of many existing libraries. In ths case we will use ",[459,12708,12075],{}," library.\nPromise interface from ",[459,12711,12075],{}," needs to be registred with ",[459,12714,12715],{},"chai-http"," in order to support ",[459,12718,12370],{}," method which returns promise.",[426,12721,12722,12723,12726],{},"To make test to be asynchronous with promise, the only thing to do is to return promise. This is why we return ",[459,12724,12725],{},".then"," in the test.",[426,12728,12661,12729],{},[977,12730,12731],{"href":12731,"rel":12732},"https:\u002F\u002Ftheintern.github.io\u002Fintern\u002F#async-tests",[981],[8112,12734,12736],{"id":12735},"improvements","Improvements",[426,12738,12739,12740,12743],{},"Intern allows to execute suites simultaneously. If we start many end to end suites it might turn out that we are using same port. To detect free port and use it I use ",[459,12741,12742],{},"portfinder"," library.",[8004,12745,9101],{"id":10721},[426,12747,12748],{},"In this post I demonstrated how to set up testing environment for NodeJS application using Intern framework and Grunt task runner. Then I've modified simple unit tests to run local server with endpoints which needs to be tested. After that we are able to call them and assure that responses are correct. Please notice that the speed of set up the whole server doesn't differ so much from unit tests.",[426,12750,10727,12751],{},[977,12752,12753],{"href":12753,"rel":12754},"https:\u002F\u002Fgithub.com\u002Fkospiotr\u002Fhello-js\u002Ftree\u002Fmaster\u002Fintern-end-to-end-tests",[981],[984,12756,12757],{},"html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}",{"title":457,"searchDepth":471,"depth":471,"links":12759},[12760,12761,12765,12766,12770,12774,12775,12779,12780,12781],{"id":8020,"depth":471,"text":8021},{"id":8109,"depth":471,"text":8110,"children":12762},[12763,12764],{"id":8114,"depth":478,"text":8115},{"id":8124,"depth":478,"text":8125},{"id":8345,"depth":471,"text":8346},{"id":8478,"depth":471,"text":8479,"children":12767},[12768,12769],{"id":8485,"depth":478,"text":8486},{"id":8507,"depth":478,"text":8508},{"id":8607,"depth":471,"text":8608,"children":12771},[12772,12773],{"id":8611,"depth":478,"text":8612},{"id":8624,"depth":478,"text":8625},{"id":11305,"depth":471,"text":11306},{"id":8829,"depth":471,"text":8830,"children":12776},[12777,12778],{"id":8836,"depth":478,"text":8837},{"id":9078,"depth":478,"text":9079},{"id":9100,"depth":471,"text":9101},{"id":11754,"depth":471,"text":11755},{"id":12587,"depth":471,"text":12588,"children":12782},[12783,12784,12785,12786],{"id":12591,"depth":478,"text":12592},{"id":12615,"depth":478,"text":12616},{"id":12668,"depth":478,"text":12669},{"id":12735,"depth":478,"text":12736},"2015-03-03","Testing REST with Intern",{"layout":993},"\u002Fblog\u002F2015-03-03-end-to-end-tests-with-intern",{"title":10772,"description":12788},"2.blog\u002F2015-03-03-end-to-end-tests-with-intern","EbizDXNo7BfFtvptRgfyij8TqQafLtiDFQHUv5xO7Sc",{"id":12795,"title":12796,"authors":409,"badge":409,"body":12797,"date":12888,"description":12889,"extension":991,"image":409,"meta":12890,"navigation":474,"path":12891,"seo":12892,"stem":12893,"__hash__":12894},"posts\u002F2.blog\u002F2015-04-06-testing_with_intern.md","Testing with Intern",{"type":423,"value":12798,"toc":12886},[12799,12801,12804,12808,12811,12857,12860],[8004,12800,8007],{"id":8006},[426,12802,12803],{},"In the previous posts [\"Testing Node applications with Intern framework\"]({% post_url 2015-03-01-unit-tests-with-intern %}) I demostrated how to set up testing environment for unit tests with Intern and Grunt and in [\"REST end to end testing Node applications with Intern framework\"]({% post_url 2015-03-03-end-to-end-tests-with-intern %}) I demonstrated how to test REST endpoints with end to end tests in a speed of unit tests.\nToday I will show how to organize Quality Assurance environment for Unit, Integration and Functional tests.",[8004,12805,12807],{"id":12806},"grunt-and-task-conventions","Grunt and task conventions",[426,12809,12810],{},"Here are tasks which we are using while testing:",[439,12812,12813,12818,12824,12830,12835,12841,12846,12852],{},[442,12814,12815,12817],{},[459,12816,9017],{}," - execute all tests (unit, integration, functional)",[442,12819,12820,12823],{},[459,12821,12822],{},"testing"," - as above in a watch loop, reexecutes tests when implementation or test sources changes",[442,12825,12826,12829],{},[459,12827,12828],{},"test-unit"," - execute unit tests",[442,12831,12832,12823],{},[459,12833,12834],{},"testing-unit",[442,12836,12837,12840],{},[459,12838,12839],{},"test-functional"," - execute functional",[442,12842,12843,12823],{},[459,12844,12845],{},"testing-functional",[442,12847,12848,12851],{},[459,12849,12850],{},"test-integration"," - execute integration tests",[442,12853,12854,12823],{},[459,12855,12856],{},"testing-integration",[426,12858,12859],{},"Require",[439,12861,12862,12868,12874,12880],{},[442,12863,12864,12867],{},[459,12865,12866],{},"var suite = require('intern!object')"," - require internal intern suite object",[442,12869,12870,12873],{},[459,12871,12872],{},"var tester = require('..\u002Flib\u002FrestServerTester')"," - require AMD styled file",[442,12875,12876,12879],{},[459,12877,12878],{},"var express = require('intern\u002Fdojo\u002Fnode!express')"," - require CommonJS module",[442,12881,12882,12885],{},[459,12883,12884],{},"var swagger = require('intern\u002Fdojo\u002Fnode!..\u002F..\u002Findex')"," - require custom CommonJS module from relative path",{"title":457,"searchDepth":471,"depth":471,"links":12887},[],"2015-04-06","Quality assurance with Intern",{"layout":993,"draft":474},"\u002Fblog\u002F2015-04-06-testing_with_intern",{"title":12796,"description":12889},"2.blog\u002F2015-04-06-testing_with_intern","42i7frZkZUNn0wXqetZKhjUswiGFZXGwT8qrJgF_rHE",{"id":12896,"title":12897,"authors":409,"badge":409,"body":12898,"date":12926,"description":12927,"extension":991,"image":409,"meta":12928,"navigation":474,"path":12929,"seo":12930,"stem":12931,"__hash__":12932},"posts\u002F2.blog\u002F2016-03-14-prepare-environment-for-releasing-to-maven-central.md","Prepare environment for releasing to Maven Sentral Repository",{"type":423,"value":12899,"toc":12924},[12900,12904,12918],[8004,12901,12903],{"id":12902},"prepare-environment","Prepare environment",[426,12905,12906,12907,12910,12911,12914,12915],{},"Generate key for signing build package:\nimport existing key ",[459,12908,12909],{},"gpg2 --keyserver x-hkp:\u002F\u002Fpool.sks-keyservers.net --recv-keys 9EBCB0B3","\nor generate new ",[459,12912,12913],{},"gpg --gen-key","\nand export it ",[459,12916,12917],{},"gpg2 --keyserver hkp:\u002F\u002Fpool.sks-keyservers.net --send-keys A6BAB25C",[426,12919,12920,12921],{},"install if needed ",[459,12922,12923],{},"sudo aptitude install haveged",{"title":457,"searchDepth":471,"depth":471,"links":12925},[],"2016-03-14","Generate key for signing build package:\nimport existing key gpg2 --keyserver x-hkp:\u002F\u002Fpool.sks-keyservers.net --recv-keys 9EBCB0B3\nor generate new gpg --gen-key\nand export it gpg2 --keyserver hkp:\u002F\u002Fpool.sks-keyservers.net --send-keys A6BAB25C",{"layout":993,"draft":474},"\u002Fblog\u002F2016-03-14-prepare-environment-for-releasing-to-maven-central",{"title":12897,"description":12927},"2.blog\u002F2016-03-14-prepare-environment-for-releasing-to-maven-central","2IEXGR3aYxa69j3DBZ-bniG7wK8R3uXSadryzq-4kc0",{"id":12934,"title":12935,"authors":409,"badge":409,"body":12936,"date":13254,"description":457,"extension":991,"image":409,"meta":13255,"navigation":474,"path":13256,"seo":13257,"stem":13258,"__hash__":13259},"posts\u002F2.blog\u002F2016-09-17-ng2-uikit-spa-app.md","Angular 2 + uikit application",{"type":423,"value":12937,"toc":13252},[12938,12942,12955,12959,12966,12972,12975,12981,12984,12990,12996,12999,13005,13009,13016,13022,13024,13030,13033,13040,13046,13052,13058,13063,13069,13076,13082,13088,13094,13097,13099,13105,13109,13112,13119,13125,13133,13139,13142,13147,13153,13159,13165,13167,13169,13175,13179,13186,13189,13195,13198,13204,13210,13216,13222,13225,13245,13247],[8004,12939,12941],{"id":12940},"prerequisite","Prerequisite",[439,12943,12944,12946,12949],{},[442,12945,282],{},[442,12947,12948],{},"NodeJS and NPM",[442,12950,12951,12952],{},"global NPM libraries: ",[459,12953,12954],{},"sudo npm install -g webpack webpack-dev-server typescript",[8004,12956,12958],{"id":12957},"init-angular-2-project-with-seed","Init Angular 2 project with seed",[426,12960,12961,12962,3095],{},"Clone repo from ",[977,12963,12964],{"href":12964,"rel":12965},"https:\u002F\u002Fgithub.com\u002Fangular\u002Fangular2-seed",[981],[452,12967,12970],{"className":12968,"code":12969,"language":3262},[3260],"git clone git@github.com:angular\u002Fangular2-seed.git ng2uikit-app\n",[459,12971,12969],{"__ignoreMap":457},[426,12973,12974],{},"Install dependencies:",[452,12976,12979],{"className":12977,"code":12978,"language":3262},[3260],"cd ng2uikit-app\nnpm install\n",[459,12980,12978],{"__ignoreMap":457},[426,12982,12983],{},"Run app:",[452,12985,12988],{"className":12986,"code":12987,"language":3262},[3260],"npm start\n",[459,12989,12987],{"__ignoreMap":457},[426,12991,7872,12992],{},[977,12993,12994],{"href":12994,"rel":12995},"http:\u002F\u002Flocalhost:3000",[981],[426,12997,12998],{},"Result:",[426,13000,13001],{},[3284,13002],{"alt":13003,"src":13004},"NG2 seed app","\u002Fposts\u002Fassets\u002F2016-09-17_init-ng-app-page.png",[8004,13006,13008],{"id":13007},"uikit-styles","uikit styles",[426,13010,13011,13012,13015],{},"Replace",[459,13013,13014],{},"home.html"," content:",[452,13017,13020],{"className":13018,"code":13019,"language":3262},[3260],"\u003Cdiv class=\"uk-container uk-container-center uk-margin-top uk-margin-large-bottom\">\n\n  \u003Cdiv class=\"uk-grid\" data-uk-grid-margin>\n    \u003Cdiv class=\"uk-width-medium-1-1\">\n\n      \u003Cdiv class=\"uk-vertical-align uk-text-center\"\n           style=\"background: url('data:image\u002Fsvg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gR2VuZXJhdG9yOiBBZG9iZSBJbGx1c3RyYXRvciAxNi4wLjQsIFNWRyBFeHBvcnQgUGx1Zy1JbiAuIFNWRyBWZXJzaW9uOiA2LjAwIEJ1aWxkIDApICAtLT4NCjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+DQo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkViZW5lXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4Ig0KCSB3aWR0aD0iMTEzMHB4IiBoZWlnaHQ9IjQ1MHB4IiB2aWV3Qm94PSIwIDAgMTEzMCA0NTAiIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDExMzAgNDUwIiB4bWw6c3BhY2U9InByZXNlcnZlIj4NCjxyZWN0IGZpbGw9IiNGNUY1RjUiIHdpZHRoPSIxMTMwIiBoZWlnaHQ9IjQ1MCIvPg0KPC9zdmc+DQo=') 50% 0 no-repeat; height: 450px;\">\n        \u003Cdiv class=\"uk-vertical-align-middle uk-width-1-2\">\n          \u003Ch1 class=\"uk-heading-large\">Sample Heading\u003C\u002Fh1>\n          \u003Cp class=\"uk-text-large\">Cras justo odio, dapibus ac facilisis in, egestas eget quam. Fusce dapibus, tellus ac\n            cursus commodo.\u003C\u002Fp>\n          \u003Cp>\n            \u003Ca class=\"uk-button uk-button-primary uk-button-large\" href=\"#\">Button\u003C\u002Fa>\n            \u003Ca class=\"uk-button uk-button-large\" href=\"#\">Button\u003C\u002Fa>\n          \u003C\u002Fp>\n        \u003C\u002Fdiv>\n      \u003C\u002Fdiv>\n\n    \u003C\u002Fdiv>\n  \u003C\u002Fdiv>\n\u003C\u002Fdiv>\n",[459,13021,13019],{"__ignoreMap":457},[426,13023,12998],{},[426,13025,13026],{},[3284,13027],{"alt":13028,"src":13029},"app without styles","\u002Fposts\u002Fassets\u002F2016-09-17_app-page-no-styles.png",[426,13031,13032],{},"Need to tell webpack how to build uikit theme and bundle them with app.",[426,13034,13035,13036,13039],{},"Install uikit as a npm module. We will need it later as an runtime dependency so save it with ",[459,13037,13038],{},"--save"," :",[452,13041,13044],{"className":13042,"code":13043,"language":3262},[3260],"npm install uikit --save\n",[459,13045,13043],{"__ignoreMap":457},[426,13047,13048,13049,13039],{},"Install less and other resource loaders for webpack. We will use them only for building app so use ",[459,13050,13051],{},"--save-dev",[452,13053,13056],{"className":13054,"code":13055,"language":3262},[3260],"npm install --save-dev less-loader style-loader less url-loader file-loader\n",[459,13057,13055],{"__ignoreMap":457},[426,13059,10347,13060,13039],{},[459,13061,13062],{},"webpack.config.js",[452,13064,13067],{"className":13065,"code":13066,"language":3262},[3260],"  module: {\n    loaders: [\n      ...\n      {test: \u002F\\.less$\u002F, loader: 'style!css!less'},\n      {test: \u002F\\.woff(2)?(\\?v=[0-9]\\.[0-9]\\.[0-9])?$\u002F, loader: \"url-loader?limit=10000&mimetype=application\u002Ffont-woff\"},\n      {test: \u002F\\.(ttf|eot|svg|png|gif)(\\?v=[0-9]\\.[0-9]\\.[0-9])?$\u002F, loader: \"file-loader\"},\n    ]\n  }\n",[459,13068,13066],{"__ignoreMap":457},[426,13070,13071,13072,13075],{},"Create ",[459,13073,13074],{},"src\u002Fstyles.less"," file with content:",[452,13077,13080],{"className":13078,"code":13079,"language":3262},[3260],"@import \"..\u002Fnode_modules\u002Fuikit\u002Fthemes\u002Fdefault\u002Fuikit.less\";\n\n@icon-font-path: \"..\u002F..\u002Ffonts\"; \u002F\u002Ffixing wrong relative path\n",[459,13081,13079],{"__ignoreMap":457},[426,13083,13084,13085,3095],{},"Add as a first line to file ",[459,13086,13087],{},"main.browser.ts",[452,13089,13092],{"className":13090,"code":13091,"language":3262},[3260],"import '.\u002Fstyles.less';\n",[459,13093,13091],{"__ignoreMap":457},[426,13095,13096],{},"Need to restart watch process in order to apply new loaders.",[426,13098,12998],{},[426,13100,13101],{},[3284,13102],{"alt":13103,"src":13104},"app with styles","\u002Fposts\u002Fassets\u002F2016-09-17_app-page-with-styles.png",[8004,13106,13108],{"id":13107},"uikit-dynamic-elements","uikit dynamic elements",[426,13110,13111],{},"So far static elements like panels or buttons are showing properly. However dynamic components using javascript will fail.",[426,13113,13114,13115,13118],{},"Modify ",[459,13116,13117],{},"about.html"," file by adding on the end:",[452,13120,13123],{"className":13121,"code":13122,"language":3262},[3260],"\n\u003C!-- This is the anchor toggling the modal -->\n\u003Ca class=\"uk-button uk-button-primary\" href=\"#my-id\" data-uk-modal>Open dialog\u003C\u002Fa>\n\n\u003C!-- This is the modal -->\n\u003Cdiv id=\"my-id\" class=\"uk-modal\">\n  \u003Cdiv class=\"uk-modal-dialog uk-modal-dialog-lightbox\">\n    \u003Ca href=\"\" class=\"uk-modal-close uk-close uk-close-alt\">\u003C\u002Fa>\n    This is a dialog box\n  \u003C\u002Fdiv>\n\u003C\u002Fdiv>\n",[459,13124,13122],{"__ignoreMap":457},[426,13126,13127,13128,13132],{},"Open ",[977,13129,13130],{"href":13130,"rel":13131},"http:\u002F\u002Flocalhost:3000\u002F#\u002Fabout",[981]," page and click button. Result:",[426,13134,13135],{},[3284,13136],{"alt":13137,"src":13138},"app without js","\u002Fposts\u002Fassets\u002F2016-09-17_app-page-no-js.png",[426,13140,13141],{},"This is actually because we didn't povided all required scripts (dependencies) yet.",[426,13143,13144,13145,13039],{},"Need to install runtime dependencies. uikit is already installed, however it requires also jQuery. Install jquery runtime dependencies as a npm module and save it using ",[459,13146,13038],{},[452,13148,13151],{"className":13149,"code":13150,"language":3262},[3260],"npm install jquery --save\nnpm install imports-loader --save-dev\n",[459,13152,13150],{"__ignoreMap":457},[426,13154,13155,13156,13039],{},"Add uikit with jquery as it's dependency to be bundled for the browser. Add below code to the bottom of ",[459,13157,13158],{},"vendor.browser.ts",[452,13160,13163],{"className":13161,"code":13162,"language":3262},[3260],"require(\"imports?$=jquery\u002Fsrc\u002Fjquery!uikit\");\n",[459,13164,13162],{"__ignoreMap":457},[426,13166,13096],{},[426,13168,12998],{},[426,13170,13171],{},[3284,13172],{"alt":13173,"src":13174},"app with js","\u002Fposts\u002Fassets\u002F2016-09-17_app-page-with-js.png",[8004,13176,13178],{"id":13177},"theming","Theming",[426,13180,13181,13182],{},"Go to uikit customizer: ",[977,13183,13184],{"href":13184,"rel":13185},"http:\u002F\u002Fgetuikit.com\u002Fdocs\u002Fcustomizer.html",[981],[426,13187,13188],{},"Modify elements that you wish:",[426,13190,13191],{},[3284,13192],{"alt":13193,"src":13194},"theme customization","\u002Fposts\u002Fassets\u002F2016-09-17_customize_theme.png",[426,13196,13197],{},"Download less file, rename it to theme and put it in the app directory.",[426,13199,13200,13201,13015],{},"Example ",[459,13202,13203],{},"theme.less",[452,13205,13208],{"className":13206,"code":13207,"language":3262},[3260],"\u002F* theme: Default *\u002F\n\n\n\u002F\u002F\n\u002F\u002F General\n\u002F\u002F\n\n@global-background: rgba(94, 209, 255, 0.33);\n\n\u002F\u002F\n\u002F\u002F Icon\n\u002F\u002F\n\n@icon-font-path: \"..\u002F..\u002Ffonts\";\n",[459,13209,13207],{"__ignoreMap":457},[426,13211,13114,13212,13215],{},[459,13213,13214],{},"styles.less"," file. Mind that you can remove fix for fonts as overrides already contains fix:",[452,13217,13220],{"className":13218,"code":13219,"language":3262},[3260],"@import \"..\u002Fnode_modules\u002Fuikit\u002Fthemes\u002Fdefault\u002Fuikit.less\";\n@import \".\u002Ftheme.less\";\n",[459,13221,13219],{"__ignoreMap":457},[426,13223,13224],{},"Mind that if you have changed the default main theme then first line should be modified as follow:",[439,13226,13227,13233,13239],{},[442,13228,13229,13230],{},"Default - ",[459,13231,13232],{},"..\u002Fnode_modules\u002Fuikit\u002Fthemes\u002Fdefault\u002Fuikit.less",[442,13234,13235,13236],{},"Gradient - ",[459,13237,13238],{},"..\u002Fnode_modules\u002Fuikit\u002Fthemes\u002Fgradient\u002Fuikit.less",[442,13240,13241,13242],{},"Almost Flat - ",[459,13243,13244],{},"..\u002Fnode_modules\u002Fuikit\u002Fthemes\u002Falmost-flat\u002Fuikit.less",[426,13246,12998],{},[426,13248,13249],{},[3284,13250],{"alt":13193,"src":13251},"\u002Fposts\u002Fassets\u002F2016-09-17_customized_theme.png",{"title":457,"searchDepth":471,"depth":471,"links":13253},[],"2016-09-17",{"layout":993},"\u002Fblog\u002F2016-09-17-ng2-uikit-spa-app",{"title":12935,"description":457},"2.blog\u002F2016-09-17-ng2-uikit-spa-app","znBimFR2D2wiwSvcfPTqg-as_x7osz3XDRw6F5uGqGE",{"id":13261,"title":13262,"authors":409,"badge":409,"body":13263,"date":13422,"description":457,"extension":991,"image":409,"meta":13423,"navigation":474,"path":13424,"seo":13425,"stem":13426,"__hash__":13427},"posts\u002F2.blog\u002F2017-06-18-private-vps-with-rpi3.md","Private VPS with Raspberry PI 3",{"type":423,"value":13264,"toc":13420},[13265,13267,13275,13279,13340,13344,13352,13370,13387,13393,13401,13407,13412,13418],[8004,13266,12941],{"id":12940},[439,13268,13269,13272],{},[442,13270,13271],{},"Raspberry PI 3",[442,13273,13274],{},"Public IP (optionally)",[8004,13276,13278],{"id":13277},"install-and-configure-rpi","Install and configure RPI",[439,13280,13281,13289,13308,13327,13330],{},[442,13282,13283,13284,13288],{},"Download Raspian Litle from: ",[977,13285,13286],{"href":13286,"rel":13287},"https:\u002F\u002Fwww.raspberrypi.org\u002Fdownloads\u002Fraspbian\u002F",[981]," and unzip it",[442,13290,13291,13292,13296],{},"Copy image to the card: ",[977,13293,13294],{"href":13294,"rel":13295},"https:\u002F\u002Fwww.raspberrypi.org\u002Fdocumentation\u002Finstallation\u002Finstalling-images\u002Flinux.md",[981],[439,13297,13298,13303],{},[442,13299,13300],{},[459,13301,13302],{},"dd bs=4M if=2017-04-10-raspbian-jessie-lite.img of=\u002Fdev\u002Fmmcblk0",[442,13304,13305],{},[459,13306,13307],{},"sync",[442,13309,13310,13311],{},"Enable SSH on a headless RPI\n",[439,13312,13313],{},[442,13314,13315,13318,13319,13322,13323,13326],{},[459,13316,13317],{},"sudo mkdir \u002Fmedia\u002Fsd && sudo mount \u002Fdev\u002Fmmcblk0p1 \u002Fmedia\u002Fsd"," - mount bootable partition of the SD card\n * ",[459,13320,13321],{},"sudo touch \u002Fmedia\u002Fsd\u002Fssh"," - create ",[459,13324,13325],{},"ssh"," file on the SD card which enables SSH on boot  ",[442,13328,13329],{},"Insert SD card in the RPI, turn it on and connect to the LAN",[442,13331,13332,13335,13336,13339],{},[459,13333,13334],{},"ssh pi@192.168.1.10"," - connect via ssh where ",[459,13337,13338],{},"192.168.1.10"," is local address of the RPI",[8004,13341,13343],{"id":13342},"install-software","Install software",[439,13345,13346,13349],{},[442,13347,13348],{},"Install commons\n * sudo apt-get update\n * sudo apt-get install software-properties-common vim",[442,13350,13351],{},"Install java",[452,13353,13358],{"className":13354,"code":13355,"language":13356,"meta":13357,"style":457},"language-sudo shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","sudo mkdir \u002Fopt\u002Fjdk\u002F && \\\nsudo tar xvzf \u002Ftmp\u002Fjdk.tar.gz -C \u002Fopt\u002Fjdk\u002F\n","sudo","wget -O \u002Ftmp\u002Fjdk.tar.gz --header \"Cookie: oraclelicense=accept-securebackup-cookie\" http:\u002F\u002Fdownload.oracle.com\u002Fotn-pub\u002Fjava\u002Fjdk\u002F8u131-b11\u002Fd54c1d3a095b4ff2b6607d096fa80163\u002Fjdk-8u131-linux-arm64-vfp-hflt.tar.gz",[459,13359,13360,13365],{"__ignoreMap":457},[462,13361,13362],{"class":464,"line":465},[462,13363,13364],{},"sudo mkdir \u002Fopt\u002Fjdk\u002F && \\\n",[462,13366,13367],{"class":464,"line":471},[462,13368,13369],{},"sudo tar xvzf \u002Ftmp\u002Fjdk.tar.gz -C \u002Fopt\u002Fjdk\u002F\n",[439,13371,13372,13384],{},[442,13373,13374,13375],{},"Install Jenkins\n",[439,13376,13377],{},[442,13378,13379,13380],{},"Instructions: ",[977,13381,13382],{"href":13382,"rel":13383},"http:\u002F\u002Fkospiotr.github.io\u002Fwiki\u002Fjenkins\u002F",[981],[442,13385,13386],{},"Install GIT",[452,13388,13391],{"className":13389,"code":13390,"language":3262},[3260],"sudo apt-get install git\n",[459,13392,13390],{"__ignoreMap":457},[439,13394,13395,13398],{},[442,13396,13397],{},"Configure ssh keys for jenkins user",[442,13399,13400],{},"Install Docker",[452,13402,13405],{"className":13403,"code":13404,"language":3262},[3260],"curl -sSL https:\u002F\u002Fget.docker.com | sh\n",[459,13406,13404],{"__ignoreMap":457},[439,13408,13409],{},[442,13410,13411],{},"Grant permissions for Docker to Jenkins",[452,13413,13416],{"className":13414,"code":13415,"language":3262},[3260],"sudo usermod -aG docker jenkins\n",[459,13417,13415],{"__ignoreMap":457},[984,13419,986],{},{"title":457,"searchDepth":471,"depth":471,"links":13421},[],"2018-06-18",{"layout":993},"\u002Fblog\u002F2017-06-18-private-vps-with-rpi3",{"title":13262,"description":457},"2.blog\u002F2017-06-18-private-vps-with-rpi3","c2tDW2kzRCtGxLySoxEHTbzHPnDxF_wisQbhl4YgfwQ",1788257053824]