PlantATree

Tak nějak jsem se naučil, že nejzajímavější a nejpoužívanější jsou ty úplně nejjednodušší aplikace, o kterých by člověk při návrhu nějakého sofistikovaného systému (aka švýcarského nože) řekl, že jsou úplně na nic. Před časem jsme vymysleli úplně dokonalý tajný projekt, který měl mít množství funkcí a měl být napsaný hned a hned vržen do světa. … Pokračovat ve čtení „PlantATree“

Tak nějak jsem se naučil, že nejzajímavější a nejpoužívanější jsou ty úplně nejjednodušší aplikace, o kterých by člověk při návrhu nějakého sofistikovaného systému (aka švýcarského nože) řekl, že jsou úplně na nic. Před časem jsme vymysleli úplně dokonalý tajný projekt, který měl mít množství funkcí a měl být napsaný hned a hned vržen do světa. Napsal jsem množství prototypů, které teˇd samostatně živoří bez frontendu a defakto bez vzájemné propojenosti. Proč? Možná je toho na jednoho člověka hodně, nebo spíš je to hrozně rozprostřené do šířky a něco takového poskládat dohromady, nedejbože udržovat a upravovat…fuj! Proto jsem si to soukromě (potají) ořezal, pouze na části základní funkčnosti a už to bylo lepší, prototypy se začaly skládat dohromady jako skládačka. Ovšem lepidla je málo (času – přece jenom když člověk dělá na několika rozdílných projektech, z nichž na některé se soustředí více, na některé pouze ve zbytcích času, potom zjistí, že se ve větší míře pouze seznamuje s tím, co že to před těmi čtrnácti vlastně udělal a čím by teˇd měl pokračovat). Proto jsem to ořezal ještě více a stvořím jenom drobnost, kterou budu vidět, že funguje a na jádro budu moct postupem času lepit další kousky. Drobnost, která nebude potřebovat moc lepidla, protože nebude mít téměř žádné funkce a dohromady nebude dělat téměř nic. Takže se, drahý světe, nechej překvapit, tímhle blogpostem jsem si dal jakýsi závazek, tak to budu muset udělat :-).

A cožeto? Geolokační hříčka – nebo spíš platforma postavená na SpringMVC, která bude nabízet RESTful rozhraní pro jistý druh „checkinů“. K tomu spytlíkuju Android aplikaci a celé to poběží na CloudFoundry, které bych tímto projektem rád vyzkoušel. GAE asi definitivně hážu za hlavu díky nemožnosti ukládání polymorfů :-).

Toshiba AC100

Dneska jsem si byl v krámu vyzvednout novou hračku – netbook s Tegrou a běžícím Androidem. Chvála a vlastnosti je možné se dočíst všude možně po webu, já bych s dovolením shrnul některé moje první dojmy (teda funkční, nebudu se tu rozplývat, jak je to tenké, lehké a nehlučné :-)).   První dojmy jsou takové … Pokračovat ve čtení „Toshiba AC100“

Dneska jsem si byl v krámu vyzvednout novou hračku – netbook s Tegrou a běžícím Androidem. Chvála a vlastnosti je možné se dočíst všude možně po webu, já bych s dovolením shrnul některé moje první dojmy (teda funkční, nebudu se tu rozplývat, jak je to tenké, lehké a nehlučné :-)).

 

ToshibaAC100
ToshibaAC100

První dojmy jsou takové rozporuplné, nějak tam nic nefunguje. Zvyk z dotykového ovládání mě pořád nutí se dotýkat displeje, touchpad pořád zůstává opomenut, protože ta myš je taková nějaká…prostě divná, takže používám k ovládání především kurzorové klávesy, ale i tak se to chová jinak, než normální systém (checkboxy se neoznačují mezerníkem, ale enterem, klávesa tab neskáče na další prvek formuláře…ale to chce zvyk a cvik). Netbook byl dodán s Eclairem (2.1), ale po chvíli laborování (především s hledáním, kde potvrdit EULU a TOS, aby mě to vůbec pustilo dálo, protože to hned po startu celé spadlo) mi byl nabídnut update na Froyo (2.2) tak updatuju a mezitím hledám informace, jak tam dostat googleApps a píšu tenhle post :-). Stávající Camangi market mě přinutil se zaregistrovat, ale nedokáže se spustit – ihned po přihlášení padne na hubu a zkouší se spustit znovu, takže kdybych nebyl několikaletý androiďák, asi bych tahal ven baterku. Další věc, která mě zpočátku zarazila, je občasné vypnutí displeje (po patřičném timeoutu samozřejmě), jak je zvykem – nejprve se intenzita svitu zmenší na polovinu, pár vteřin počká a potom zhasne. Ovšem když pohasne a já hýbu myší a třískám do klávesnice, tak stejně zdechne (naštěstí jen občas). Další nedoladěností je zobrazení neexistence datového připojení v horní liště. (Po update na 22 je to ok) Mám verzi pouze s wifi, takže bych čekal, že si výrobce dá práci a upraví image, aby se tam nezobrazovalo to, co nemá. Ale tak co už, ničemu to nevadí.

Nyní bych si dovolil v několika krocích sepsat postup pro nahrání googleApps, protože nalezené howto je takove nějaké necelistvé (bez odkazů a konkrétních informací). Vycházím z návodu pro dodání googleApps do emulátoru v rámci SDK, který jsem absolvoval o víkendu a zadařil se.

Prvním krokem budiž update na 2.2 pomocí Toshiba Service Station, jak je vidět na screenshotu, já již mám oněch cca 200MB skoro staženo.

SystemUpdate
Průběh aktualizace

Zatímco se instaluje aktualizace bych doporučil projít můj starý blogpost, bude se nemálo hodit.

Také by asi bylo vhodné zmínit následující: podle tohoto návodu by měl postupovat ten, kdo alespoň trochu ví, co dělá. Je vhodné si jej nejprve projít, aby se předešlo nejasnostem, a až teprve poté postupovat krok za krokem. Také předesílám, že nechci nést (a ani neponesu) následky za možné způsobené problémy způsobené aplikováním níže uvedených postupů.

No a protože potřebujeme roota, bude nutné to nějak provést, takže je vhodné začít na XDA developers a pořídit si SuperOneClick (mělo by to fungovat i pod Linuxem, ověřím v dalším kroku, teď instaluju mono). (Nefunguje)

Tak z jiného soudku, asi bude potřeba root, čili návod zde. (nefunguje)

Ok, tak po hlavě do toho konečně, už to mám týden rootnuté a pořad nemám dopsaný tenhle blogpost. Nvidia taky odstranila Linux4Tegra projekt z jejich downloadů, spálil jsem si obličej a mnohé další radosti, jako třeba objevení důvodu zřejmého blbnutí předchozího návodu – kvůli oprávněním, takže to zkouším jinak:

  1. Stáhnout balík s Froyem pro devBoard Tegra 250 ze stránek nvidie, rozbalit a nainstalovat, bude potřeba aplikace nvflash,
  2. stáhnout upravený bootloader – fastboot.stock.bin od Ilya Petrova z repozitáře na GitHubu,
  3. stáhnout aktualizovanou implementaci wpa2 – wpa_supplicant včetně konfiguračního souboru, také z GitHubu,
  4. gapps – nalézající se v Cyanogenově packu s Google Aplikacemi, Froyo je v CM6, stahovat je samozřejmě vhodné balíček pro tegru, v tomto případě gapps-mdpi-tegra-20101020-signed.zip,
  5. stáhnout emulátor terminálu od jackpala (opravdu je tam i binárka, je potřeba trochu hledat ;-)), aby byl přítomen přímo na systémové partišně,
  6. stáhnout superuser aplikaci a su binárku, odkaz je ve vlákně na XDAdevelopers,

V tomto okamžiku již není potřeba nic dalšího stahovat, takže můžeme flashnout bootloader a stáhnout osmou partition, což je /system. Je nutné zařízení nastartovat v recovery režimu, takže vypnout Toshibu, napíchnout USB kabelem, přidržet Ctrl+Esc a podržet power na pár vteřin, power po chvíli pustit a když se rozsvítí LEDka power, pustit i zbytek. Nic víc se nerozsvítí, obrazovka zůstane mrtvá. (v tomto okamžiku předpokládám bezproblémovou komunikaci zařízení a počítače, jak jsem uváděl výše, dle starého blogpostu) Pro následující kroky je potřeba být rootem, takže pod sudem 🙂 nejprve flashneme nový zavaděč a potom přečteme onu osmou osudovou:

[sourcecode language=“plain“]LD_LIBRARY_PATH=. ./nvflash –bl ../prebuilt/fastboot.stock.bin –go
LD_LIBRARY_PATH=. ./nvflash -r –read 8 part-8.img[/sourcecode]

Získanou partition je teď možné přes loop připojit a začít kopírovat (přepisovat):

  1. do adresáře /app přijde Term.apk, Superuser.apk, Vending.apk a GoogleServicesFramework.apk (dvě poslední z cyanogen gapps balíku). Je vhodné překontrolovat vlastníka – ve všech případech by to měl být root:root;
  2. v balíku od Cyanogena jsou ještě adresáře etc, framework a lib, je vhodné je kompletně zkopírovat na odpovídající místo a nastavit všude opět vlastníka root:root (řeč je pouze o těchto adresářích, v žádném případě ne o kompletním adresáři app!!);
  3. teď je na řadě wpa_supplicant, doporučuji si původní včetně konfiguráku zazálohovat (lokálně – *.bak), zálohu původního image 8. partition pokládám za samozřejmost. Ve staženém balíku se soubor nachází oba soubory nacházejí v podadresáři wifi – takže binárka do /bin a konfigurák do /etc/wifi, opět pozor na vlastníka a práva – mělo by to vypadat nějak takhle: [sourcecode language=“plain“]-rwxr-xr-x 1 root 2000 337656 2011-03-21 23:18 wpa_supplicant
    [/sourcecode]
  4. zkopírovat do adresáře /bin binárku su ze stejného balíku, ve kterém se nacházel Superuser.apk. Tady ovšem pozor na oprávnění, bude potřeba SUID (pro stručnost řekněme chmod 6755) s výsledkem:[sourcecode language=“plain“]-rwSr-sr-t 1 root 2000 26264 2011-03-29 12:51 su[/sourcecode]

A je nakopírováno, takže je možné odmountnout image a přenést jej zpátky do zařízení, opět pomocí utility nvflash:

[sourcecode language=“plain“]shmoula tegra_froyo_20110207 # LD_LIBRARY_PATH=. ./nvflash -r –download 8 part8.img
Nvflash started
[resume mode]
sending file: part8.img
/ 314572800/314572800 bytes sent
part8.img sent successfully[/sourcecode]

Hotovo, teď je možné Toshibu vypnout (podržet power), odpojit usb kabel a provést wipe (tovární nastavení): takže podržet tlačítko home a power a v objevivším se menu vybrat první volbu (aka zmáčknout klávesu 1). Chvilku to potrvá a potom se systém sám restartuje a naběhne úvodní Toshibácké nastavení data, wifi… takže ponastavovat a po připojení je možné v menu spustit market a pomocí průvodce se přihlásit do svého googleAccountu.

Zjištěné problémy:

  1. Market je stabilní asi jako jistý známý systém jisté známé firmy, spíše ještě méně, ale aspoň funguje 🙂
  2. Občas bývají problémy s připojením k neznámé wifi, proto přímo v zařízení existuje vytvořená kopie wpa_supplicant.bak, příkaz su a možnost remountnutí /system partition pro rw
  3. Terminal.apk v některých (neznámých) případech nefunguje, je nutné jej nainstalovat z marketu

MVC and Spring surf

One of things I missed in Spring Surf are Models and Controllers. I tried many ways to get them working, but still no useful solution. So I chose really simple way to do that – to define another dispatcher and to play with urlrewrite. In this post I’ll describe what I did and as a … Pokračovat ve čtení „MVC and Spring surf“

One of things I missed in Spring Surf are Models and Controllers. I tried many ways to get them working, but still no useful solution. So I chose really simple way to do that – to define another dispatcher and to play with urlrewrite. In this post I’ll describe what I did and as a little bonus you’ll find a breathtaking example 🙂 – YUI based Ajax whisperer.

Let’s start with empty Spring Surf skeleton:

project --topLevelPackage cz.shmoula.controllers
surf install
perform eclipse

Now add dispatcher – in web.xml we have to define new servlet with name controller, loaded as second and with url-pattern /app (default dispatcher is mapped to /service), which is filtered by urlrewrite.

<servlet>
  <servlet-name>controller</servlet-name>
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  <load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
  <servlet-name>controller</servlet-name>
  <url-pattern>/app/*</url-pattern>
</servlet-mapping>

In next step we’ll need web application config – Spring names them as -servlet.xml prefixed with servlet name. So let’s create controller-servlet.xml in WEB-INF (in STS New/Spring bean configuration file) and add some useful stuff there: for first we want to use annotations for our controllers, so let’s add there two beans – DefaultAnnotationHandlerMapping and AnnotationMethodHandlerAdapter.

<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />

Then we need to define where are our controllers lying, so let’s define base package.

<context:component-scan base-package="cz.shmoula.controllers.controller" use-default-filters="false">
  <context:include-filter expression="org.springframework.stereotype.Controller" type="annotation" />
</context:component-scan>

Last thing is to tell, where will be our views and which suffix they use.

<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  <property name="prefix" value="/WEB-INF/jsp/" />
  <property name="suffix" value=".jsp" />
</bean>

Okay, folks, that’s almost all! Now the interesting part: Writing the controller. Make a class in package we defined earlier. It should extend some AbstractController or another stuff, but it’s not necessary, we’ll simple it! 😉 Put a test method inside:

package cz.shmoula.controllers.controller;

@Controller
public class AutocompleteController{

  @RequestMapping(value = "/test")
  public String test(Model model){
    model.addAttribute("attribute", "Some sample string");
    return "test";
  }
}

That’s our controller. Now we need a view. Previously we defined parameters for view resolver and in controller we’re returning name of our model. Putted together result is: /WEB-INF/jsp/test.jsp

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Test page backed by controller</title>
  </head>
  <body>
    <h1>Hi, what we have there?</h1>
    <p>${attribute}</p>
  </body>
</html>

Last thing to do is to define some rules for urlrewrite. We’ll try to forward all /app/ requests to our dispatcher and anything else to Default Spring Dispatcher. That’s done by these rules (urlrewrite.xml):

<rule>
  <from>/app/(.*)</from>
  <to>/app/$1</to>
</rule>
<rule>
  <from>/</from>
  <to>/service/</to>
</rule>

Done? So let’s test it! Run it up and open browser at http://localhost:8080/controllers/app/test. Does it work? I hope so!

Test page
Test page

That was the first part – worst one, now came pure fun – some functionality. We want to implement some buzzlike thingy as Autocompletion is – whisperer. To keep it simple our model layer will be just a Collection with Strings, so let’s modify our controller with constructor:

private Collection<String> termList = new HashSet<String>();
public AutocompleteController() {
    termList.add("Prague");
    termList.add("Paris");
    termList.add("Poznan");
}

Now we need controller code – something returning some results. So at /autocomplete will be routine, which waits for „query“parameter with part of String, which tries to find in termList and return:

@RequestMapping(value = "/autocomplete")
public void autocomplete(HttpServletRequest httpRequest, Model model) {
    String query = httpRequest.getParameter("query");
    String response = "";

    if (query != null) {
        for (Iterator<String> i = termList.iterator(); i.hasNext();) {
            String term = i.next();
            if (term.startsWith(query))
                response += "n" + term;
        }
    }
    model.addAttribute("response", response);

}

Now we have to render our model through something, so add view /WEB-INF/jsp/autocomplete.jsp:

${response }

And now to add all that into widget. Let’s extend calendar widget in /WEB-INF/webscripts/calendar – first add styles and YUI scripts into calendar.get.head.ftl:

<link type="text/css" rel="stylesheet" href="http://yui.yahooapis.com/2.8.2r1/build/autocomplete/assets/skins/sam/autocomplete.css">
<script src="http://yui.yahooapis.com/2.8.2r1/build/yahoo-dom-event/yahoo-dom-event.js"></script>
<script src="http://yui.yahooapis.com/2.8.2r1/build/datasource/datasource-min.js"></script>
<script src="http://yui.yahooapis.com/2.8.2r1/build/connection/connection-min.js"></script>
<script src="http://yui.yahooapis.com/2.8.2r1/build/autocomplete/autocomplete-min.js"></script>

<style type="text/css">
    #myAutoComplete {
        width:25em;
        padding-bottom:2em;
    }
</style>

The last step is to create div and put a script into calendar.get.html.ftl:

<div>
    <label for="myInput">Autocomplete:</label>
    <div id="myAutoComplete">
        <input id="myInput" type="text">
        <div id="myContainer"></div>
    </div>
</div>
<script type="text/javascript">
  YAHOO.example.BasicRemote = function() {
    var oDS = new YAHOO.util.XHRDataSource("/controllers/app/autocomplete");
    oDS.responseType = YAHOO.util.XHRDataSource.TYPE_TEXT;
    oDS.responseSchema = {
      recordDelim: "n",
      fieldDelim: "t"
    };
    oDS.maxCacheEntries = 5;
    var oAC = new YAHOO.widget.AutoComplete("myInput", "myContainer", oDS);
    return {
      oDS: oDS,
      oAC: oAC
    };
  }();
</script>

And that should be all, now let’s test it, if it works! So open http://localhost:8080/controllers/calendar and voila…

Working autocompletion
Working autocompletion

Ok, that’s all for this post, looks like it works! So you can download backup of this code somewhere around here and enjoy it on your own devbox. Keep looking forward for next stuff, maybe using facebook login with Spring social, who knows ;-).

JSP based components in Spring Surf

In my last blogpost we got Java backed webscripts working, now let’s try something completely different: defining page snippet as a component in .JSP. Just let’s continue with our last code, which is possible to download, but it’s not necessary, it’s possible to build it all on green meadow (aka after project in roo is … Pokračovat ve čtení „JSP based components in Spring Surf“

In my last blogpost we got Java backed webscripts working, now let’s try something completely different: defining page snippet as a component in .JSP. Just let’s continue with our last code, which is possible to download, but it’s not necessary, it’s possible to build it all on green meadow (aka after project in roo is created and surf installed).

First thing to do is to add dependency for jstl into Maven’s pom.xml and then update maven dependencies and refresh our project in Eclipse.

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>com.springsource.javax.servlet.jsp.jstl</artifactId>
    <version>1.2.0</version>
</dependency>

Now you can get glue on Spring forums, or trust me and create new component type with JSP Renderer: it’s needed to create new directory – /WEB-INF/classes/surf/site/component-types and inside new component type configuration – test.xml.

<?xml version="1.0" encoding="UTF-8"?>
<component-type>
    <id>test</id>
    <title>Test Component Type</title>
    <description>Test Component Type</description>

    <processor mode="view">
        <id>jsp</id>
        <jsp-path></jsp-path>
    </processor>
</component-type>

Jsp-path is at this time undefined, because we haven’t created any page yet. So let’s do something with that. We need to create new template and new template instance:

roo> surf template create --path test
Created SRC_MAIN_WEBAPP/WEB-INF/templates/test.ftl
roo> surf template instance create --id test --path templates --template test
Created SRC_MAIN_WEBAPP/WEB-INF/templates/test.xml

At this time we have Freemarker template (test.ftl) and template instance (test.xml) inside directory /WEB-INF/templates. We need to edit those files. First let’s add following code into test.ftl. There are four regions defined – three of them inside template scope (already defined by installation of Surf addon) and one with page scope, which we’ll define and bind later.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" >
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>${page.title}</title>
  </head>

  <body>
    <div id="page">
      <div id="header">
        <@region id="header" scope="template" />
      </div>
      <div id="horznav">
        <@region id="horznav" scope="template" />
      </div>
      <div id="content">
        <@region id="content" scope="page" />
      </div>
      <div id="footer">
        <@region id="footer" scope="template" />
      </div>
    </div>
  </body>
</html>

Following code (template instance) is definition of components in template scope and is also located in templates directory: test.xml.

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<template-instance>
  <title>test</title>
  <description>Instance of test</description>
  <template-type>test</template-type>
  <components>
    <component>
      <region-id>header</region-id>
      <url>/company/header</url>
    </component>
    <component>
      <region-id>horznav</region-id>
      <url>/navigation/horizontal</url>
    </component>
    <component>
      <region-id>footer</region-id>
      <url>/company/footer</url>
    </component>
  </components>
</template-instance>

Now we can create new page based on previously defined template-instance and add link to our new page to horizontal bar. For those actions we can use roo:

roo> surf page create --id test --path pagestest --templateInstance test
Created SRC_MAIN_WEBAPP/WEB-INF/pages/test
Created SRC_MAIN_WEBAPP/WEB-INF/pages/test/test.xml

roo> surf page association create --sourceId home --destId test
Managed SRC_MAIN_WEBAPP/WEB-INF/pages/home/home.xml

As written in roo output, directory test inside pages is created and test.xml within. This file is page configuration and we have to define our content for region defined in template. But not necessary, it’s good idea to check our work now. So let’s try to Run it on server… It’s ugly, but it works! 🙂

First try
First try

That’s cool, but our aim is to create working .jsp page. How to do that? What about simply create that page? 🙂 So let’s create test.jsp inside /WEB-INF/pages/test and fill it with some simple code:

<%@ taglib prefix='c' uri='http://java.sun.com/jstl/core_rt'%>

<%@ page import="java.util.*"  %>
<%@ page contentType="text/html;charset=UTF-8" language="java"%>

<h1>Test jsp</h1>

<%
  String someText = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.";

  List<String> l = new ArrayList<String>();
  l.add("Maecenas iaculis odio id eros fermentum non tempus erat interdum.");
  l.add("Sed mi orci, dignissim vitae cursus hendrerit, congue sed odio. ");
  l.add("Vivamus quam diam, dapibus sit amet placerat a, tempus at magna.");

  session.setAttribute("someText", someText);
  session.setAttribute("l", l);
%>

<p>${someText }</p>

<c:forEach var="x" items="${l }" >
    <p>${x}</p>
</c:forEach>

That’s our page. Now we need to connect it with previously created component type – /WEB-INF/classes/surf/site/component-types/test.xml. In time of creation we omit jsp-path, so fill it up now:

<jsp-path>/WEB-INF/pages/test/test.jsp</jsp-path>

Last thing to do is to put our shiny new component-type into page. In template we defined region, which is filled in page scope. That’s that components section in page config – /WEB-INF/pages/test/test.xml. It’s good idea to add some title and some styling like border and background thanks to chrome element:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<page>
  <id>test</id>
  <title>test</title>
  <template-instance>test</template-instance>
  <authentication>none</authentication>
  <components>
    <component>
      <region-id>content</region-id>
      <component-type-id>test</component-type-id>
      <chrome>box</chrome>
      <title>JSP inside</title>
    </component>
  </components>
</page>

After rebuild and redeploy we have our jsp component working, as you can see at http://localhost:8080/webscripts/test. Congratulations, good work!

Final application look
Final application look

Ah, in case you got lost, there is package with working sourcecode for this whole example.

Freemarker templates and java backed webscripts

Wondering about output to freemarker template from java backed webscript in Spring Surf? You’re on the right place, it’s simple so I’ll try to describe it on a few lines. For first I suppose some prerequisites you have: you have Spring Roo and (or) Springsource Tool Suite (or Eclipse with plugin), you have Spring surf … Pokračovat ve čtení „Freemarker templates and java backed webscripts“

Wondering about output to freemarker template from java backed webscript in Spring Surf? You’re on the right place, it’s simple so I’ll try to describe it on a few lines. For first I suppose some prerequisites you have:

Ok, let’s get it done quickly! Create new directory, for example webscripts. Go into it, fire up roo, create a new project, install surf extension into it and create an Eclipse project:

project --topLevelPackage cz.shmoula.webscripts
surf install
perform eclipse

Now you should have base skeleton of our future app (you can also download it here) and you can import it into SpringSource Tool Suite.

Webscripts are located in src/main/webapp/WEB-INF/webscripts folder, so open that folder and create two files: example.get.html.ftl (template) and example.get.desc.xml (description).

<p>logged user: ${userId}</p>
<webscript>
      <shortname>Example</shortname>
      <description>Sample java backed webscript</description>
      <url>/example</url>
</webscript>

Now we have to create our java source code. It’s not bad idea to put webscripts to their own package, for example webscript. In that package create a new class, which extends org.springframework.extensions.webscripts.AbstractWebScript – Example. By doing that we have to implement an execute method, which is called, when webscript is executed:

@Override
public void execute(WebScriptRequest req, WebScriptResponse res)
    throws IOException {
}

Let’s fill that method. We need a model map, which holds values as pair (String)key – (Object)value. For our desired function we also need to get HttpServletRequest:

Map<String, Object> model = new HashMap<String, Object>();
HttpServletRequest httpRequest = ServletUtil.getRequest();

Now to fill up model (aka our function). Let’s find out if there is logged in user and if so, write out it’s userId:

if(AuthenticationUtil.isAuthenticated(httpRequest)){
      model.put("userId", AuthenticationUtil.getUserId(httpRequest));
}else{
      model.put("userId", "guest");
}

Final step is to put out our model. We need to get writer and renderTemplate, which we specified by its path (and also flush and close our writer):

Writer writer = res.getWriter();
String templatePath = "webscripts/example.get.html.ftl";
renderTemplate(templatePath, createTemplateParameters(req, res, model), writer);

writer.flush();
writer.close();

Last thing we have to do is to let Surf know about our shiny new webscript. You can add new bean directly inside applicationContext, but it’s not bad idea to keep them separately. So in src/main/webapp/WEB-INF/config create new Spring Bean Definition file – custom-webscripts-config.xml and put inside new bean definition:

<bean id="webscript.webscripts.example.get" class="cz.shmoula.webscript.Example" parent="webscript"/>

Now we have to import that new config: in the same directory is surf-config.xml file, so let’s add there new import:

<import resource="custom-webscripts-config.xml"/>

At this time we can run our project and visit http://localhost:8080/webscripts/example, which shows following page:

Image and video hosting by TinyPic

It’s possible to login (if you have set up user factory) as an Alfresco user and after that another userId is shown. I’m planning to write new blogpost about custom user factory and stuff like that, so be patient please. Finally, you can download source code for this example at this link. Structure of project is shown at following screenshot (note that red dots – those are modified files):

Image and video hosting by TinyPic

Finally, try to experiment with some examples from Alfresco wiki and look forward to next blogpost.

Jak jsem dělil SSD

Protože mi vypršela studentská licence na WinXP, royhodl jsem se celý systém přeinstalovat a když už, tak pořídit i nový disk. Nejprve jsem vybíral v terabajtových velikostech, ale pak se mi to rozleželo a říkám si, že je to zbytečné – proč pořizovat velký disk, když na něm stejně nic mít nebudu a tak jako … Pokračovat ve čtení „Jak jsem dělil SSD“

Protože mi vypršela studentská licence na WinXP, royhodl jsem se celý systém přeinstalovat a když už, tak pořídit i nový disk. Nejprve jsem vybíral v terabajtových velikostech, ale pak se mi to rozleželo a říkám si, že je to zbytečné – proč pořizovat velký disk, když na něm stejně nic mít nebudu a tak jako tak to bude pomalé a žravé. Praštil jsem se přes kapsu a provedl rychlé rozhodnutí pořízením SSD disku od Intelu X25-M o kapacitě celých 80GB :-). Krabička má velikost 2,5″ disku a není k ní dodávána žádná redukce do 3,5″ pozice, tak jsem ji jenom připojil a položil dovnitř bedny bez šroubování (nemá žádné mechanické součásti, tak je to jedno).

Jak jsem teda disk(-y) dělil? Jednoduše – na SSD mám pouze root o velikosti 30GB (sdb1). Na standardním disku jsem vyvedl dělení následující (bohužel jsem neměl kam zazálohovat stávající data, proto je řazení takové nešťastné):

  • na sda1 mám /tmp o velikosti 1GB
  • na sda2 se nachází /home s velikostí 15GB (mám tu pouze jeden účet, data jsou na sda5, příp. do budoucna na NAS)
  • sda3 je prázdný 25GB oddíl a čeká, až se bude na něco hodit (možná pořídím widle a tohle bude datová část, systém přijde na SSD)
  • sda5 jsou ona výše zmíněná data, 95GB mountnutých na /home/dokumenty
  • sda6 je swap o velikosti 8GB, o němž si myslím, že je zbytečný, ale poměříme a uvidíme, viz. níže
  • a konečně sda7 je /var s velikostí 4GB

Po nainstalování systému, restartu a proběhnutí POSTu, nestačilo ani bliknout logo systému a už na mě koukal login box do systému, tohle jsem vážně nečekal, rychlost neuvěřitelná! Nebudu tu měřit starty systému ani aplikací a rozebírat různé konfigurace, jsem pouhý uživatel :-). Co jsem chtěl bylo zrychlit Eclipse a kompilaci a deployování vůbec, takže jsem přesunul Eclipse tak i repozitář pro Maven do /opt. Bohužel, zrychlení příliš citelné nebylo (konkrétní čísla opravdu poskytovat nebudu, nemám), navíc pořád docházelo k zápisům, tak se Eclipse moc nenadálo a letělo zpátky z SSD, Maven repo zůstalo, protože se z něj pouze čte (v určitých fázích, samozřejmě :-)). Kořenový adresář tedy slouží pouze ke čtení, což mám měřením ověřeno, samozřejmě při aktualizacích je nutné zapisovat, ale tento zápis je omezen na minimum, díky separátnímu /var na plotnovém disku.

Další sledování ukázalo, že velikost oddílu s /var byla zvolena příliš malá, zřejmě by byl vhodný alespoň dvojnásobek, uvidíme, jak se to rozroste. Kořenový adresář je obsazen z pouhých 14%, kdežto /var už ze 24%; jak jsem napsal, jsem zvědav za nějaký čas, zatím bych se nebál. Co se týká paměti a obsazenosti swapu, tak jsem to velikostně asi zbytečně přehnal, pouhý běžící Chromium browser (nad XFCE) se tváří „relativně nenáročně“:

Stav paměti a swapu při spuštěném samotném Chromiu
Stav paměti a swapu při spuštěném samotném Chromiu

a když k tomu všemu spustím ještě Eclipse (STS) a nahodím Tomcat s několika deploynutýma aplikacema tak se to trochu změní (možná bych mohl vyzkoušet, jak s těma číslama zahiphopuje Alfresco :-)):

Stav paměti a swapu při spuštěném Chromiu, Tomcatu a STS
Stav paměti a swapu při spuštěném Chromiu, Tomcatu a STS

Jak to celé shrnout? Asi tím, že to byl dobrý kup – systém je citelně svižnější, boot je okamžitý, jen pro vývoj se zrychlení nijak citelně neprojevilo, čekal jsem víc. Teď to chce trochu času, aby se mi potvrdila i správnost rozdělení disku (a hlavně nějaké použitelné NAS řešení s RAID5 a nízkým příkonem :-D).

Spanish inquisition

I stala se mi taková nemilá věc, jako před dávnými časy. Dostal jsem banán na věhlasném českém serveru novinky.cz. Důvod? Není mi známý, pouze jsem zmínil Španělskou inkvizici. Holt asi měl někdo špatný den, nebo zaměstnávají paní Pohlovou, takže jsem jim pro jistotu napsal zpět. Odpovědi se mi bohužel nedostalo, asi to posílal automat. Škoda, … Pokračovat ve čtení „Spanish inquisition“

I stala se mi taková nemilá věc, jako před dávnými časy. Dostal jsem banán na věhlasném českém serveru novinky.cz. Důvod? Není mi známý, pouze jsem zmínil Španělskou inkvizici. Holt asi měl někdo špatný den, nebo zaměstnávají paní Pohlovou, takže jsem jim pro jistotu napsal zpět. Odpovědi se mi bohužel nedostalo, asi to posílal automat. Škoda, docela by mě zajímalo, o co šlo.

Ban na novinkách - email
Ban na novinkách

Dwarf Fortress

Jako velkého fanouška Dungeon Keepera (druhého dílu, abych byl konkrétní) mě před nějakým časem nemálo navnadila recenze na hru Dwarf Fortress a pořád jsem odkládal prvotní ponoření do hry, protože jednak nebyl čas a druhak (a především) jsem se bál náročnosti jak hry samotné, tak i náročnosti na čas (chytne a nepustí). Pak ale na … Pokračovat ve čtení „Dwarf Fortress“

Jako velkého fanouška Dungeon Keepera (druhého dílu, abych byl konkrétní) mě před nějakým časem nemálo navnadila recenze na hru Dwarf Fortress a pořád jsem odkládal prvotní ponoření do hry, protože jednak nebyl čas a druhak (a především) jsem se bál náročnosti jak hry samotné, tak i náročnosti na čas (chytne a nepustí). Pak ale na toto téma vyšel další článek, tak jsem se rozhodl, že to vyzkouším. Tenhle blogpost nemá za cíl popisovat hru, popis se dá nalézt na dvou výše zmíněných lincích, ale má sloužit jako jakýsi rozcestník pro rychlý začátek (a pro mě, abych měl všechny ty odkazy pohromadě).

Dwarf fortress
Dwarf fortress

Jak je u mě zvykem, chvíli jsem hledal informace a na českém fóru jsem jsem se dopátral na výborný mnohadílný tutoriál na blogu After Action Reporter. Ten hned v úvodu odkazuje na předpřipravený balík včetně grafického setu May Day, takže jsem stáhl tenhle balík a pustil se do čtení, resp. hraní.

MayDay
MayDay

Postupně jsem se prokousal několika díly tutoriálu a začal se ve hře docela i orientovat (teda aspoň myslím :-)). Hra mě opravdu naprosto pohltila, zapomněl jsem na čas i na povinnosti a budoval, kopal, zaplavoval, obchodoval… A to jsem ještě nevyzkoušel adventure mode, ale to má čas.

Dwarf Fortress
Dwarf Fortress

Teď jsem tomu sice pár dní nedal, protože se trápím s Polymorfismem v JDO na Google App Engine, ale jakmile toho budu mít plné zuby (a jakože mám), hned vím, jak se odreagovat. Navíc mám tip na skvělou utilitku na nastavování vlastností trpajzlíků, vypadá komplexněji, než ta zmíněná v tutoriálu (pokud to teda není jen novější verzi, nějak nemůžu najít link).

Dwarf Therapist
Dwarf Therapist

Dwarf fortress je nejenom na první pohled výborná hra. Má svůj vlastní žijící svět, svoji historii, svoje fanstránky i svůj komix. Taky množství příběhů hráčů, kteří popisují, jak vraždí elfí karavany, jak jim goblini unášejí děti… Mám taky skromný plán – umořit trpasličí ženu a přinutit jejího muže, aby z jejích kostí udělal náhrdelníky. Prý jsou trpajzlíci vysoce etičtí, ale má být možné změnit tuto jejich výchozí etiku, takže už se nemůžu dočkat na další hákování téhle hry :-).

Tišnovská padesátka 2010

Jubilejní 40. ročník Tišnovské padesátky jsem si samozřejmě nemohl nechat ujít, zvlášť, když jsem minulý ročník ostudně proležel s hadrou na krku a horkým čajem v hrnku. Šel jsem sám, se zviřátkem, a těšil jsem se jako malej Jarda, protože bylo v plánu výborné počasí, barevné listí a zajímavá trasa. Trasu jsem volil 26 km, … Pokračovat ve čtení „Tišnovská padesátka 2010“

Jubilejní 40. ročník Tišnovské padesátky jsem si samozřejmě nemohl nechat ujít, zvlášť, když jsem minulý ročník ostudně proležel s hadrou na krku a horkým čajem v hrnku. Šel jsem sám, se zviřátkem, a těšil jsem se jako malej Jarda, protože bylo v plánu výborné počasí, barevné listí a zajímavá trasa.

U Kříže
U Kříže

Trasu jsem volil 26 km, protože se mi nechtělo vstávat, navíc jsem se na delší (díky nestřídmé konzumaci alkoholických nápojů minulého večera) necítil, Dan taky nebyl připravován, tak by asi přišel o packy na delší trase :-). Vyrazil jsem pět minut před ukončením registrace (tuším před jedenáctou), aby už byl celý špalír pryč a já měl čas na focení, kochání se a loudání. Plán se zadařil, lidi jsem potkal až na první kontrole v Loučkách, kde ovšem dan s Vořechem kontrolorů působil nedobro, tak jsem spolkl trochu čaje a chlebik s cibuli a vyrazil dále.

Dolní Loučky
Dolní Loučky

Trasa byla naplánována mimo silnici, bohužel jsem odbočku nějak minul, tak jsem se prošel pod loučským viaduktem a pokračoval dále až do údolí Blahoňůvky, kde jsem byl prve. Neměl jsem ani potuchu o tomto roztomilém údolíčku, které jsem těsně před Prosatínem opustil a začal šplhat směr Deblín.

Blahoňůvka
Blahoňůvka

Teď započala nudná fáze – chytl jsem hlavní proud lidí jdoucích z padesátky, navíc cyklisti na kontrole už stihli sežrat veškeré obžérstvení, takže jsem si posloužil z vlastních zásob, vytvořil spot na Gowalle a vyrazil směrem k cíli. Trasa byla vedena podél silnice, ale nad Vohančicemi šla pořád rovně – do lesa. V těchto končinách jsem taky nikdy předtím nebyl, nabízely zajímavé výhledy na Tišnov a ve finále i sprostou střelnici na divočáky a především rozbordelovaný les po těžbě, což byla docela podpásovka.

Tišnov od lesa nad Vohančicemi
Tišnov od lesa nad Vohančicemi

Závěr ovšem nijak nepoškodil celkový dojem z výletu, který byl podpořen nádherným počasím, pěknou trasou a především všemi barvami podzimu, takže to stálo za to (viz galerie)! Po příchodu do auta si do té doby vitální Dan lehl na podlahu a dostal neuvěřitelné tiky do tlapek, tak jsem se nemohl ubránit záchvatu smíchu i přes to, že mi ho bylo líto. Ale vypadal spokojeně, navíc má diplom!

PS Hodně turistů nezdraví, tváří se po pozdravu zmateně, což mě docela udivuje, jsem zvyklý se zdravit s lidma cestou (a ne, nezdravil jsem je nějakým šíleným jazykem :-)).

Podzimni vylet na jih

Pravidelny podzimni vylet za sluncem jsem letos sfouknul s kubasem, ktery za mnou priletel ze stockholmu. Pocatecni tvrdnuti v bergamu na letisti jsem vyplnil dopsanim posledniho blogpostu z letosniho eurotripu a uz se nemohl dockat na deni nasledujici: prepravit se do Janova do meho oblibeneho hostelu a druhy den smer hranice s francii, jeji pesi … Pokračovat ve čtení „Podzimni vylet na jih“

Pravidelny podzimni vylet za sluncem jsem letos sfouknul s kubasem, ktery za mnou priletel ze stockholmu. Pocatecni tvrdnuti v bergamu na letisti jsem vyplnil dopsanim posledniho blogpostu z letosniho eurotripu a uz se nemohl dockat na deni nasledujici: prepravit se do Janova do meho oblibeneho hostelu a druhy den smer hranice s francii, jeji pesi prejiti, jizda do monaka, pote nice a saint tropez za cetnikama a zpet do bergama. Cela cesta je takovy rozplizly kosoctverec.

Mapa wuhletu
Mapa wuhletu

Konecne se mi povedlo taky neco vyfotit z letadla – chvili pred pristanim v bergamu jsem vychytal ty pekne kopecky severneji – mozna okolo lago di camo (mam to nekde najite presne na mape a srovnaval jsem to s 3d pohledem v google earth :-)). Zaroven je mozne tu fotku brat jako takovou malou reklami jiste nizkonakladovky.

Pred pristanim v Bergamu
Pred pristanim v Bergamu

Prvni nocleh venku byl par set metru nad ventimiglii po odpoledni koupacce, lasagnich a nakupu alkoholu – byl to vicemene petihvezdickovy hotel s nadhernym vyhledem – az do francie a jeste vice doprava na jizni vybezek alp, na jehoz prejiti jsme meli par nasledujicich dni.

Nocni Ventimiglia s Francii na pozadi
Nocni Ventimiglia s Francii na pozadi

Pesi prechod zapocal asi 20km ve vnitrozemi – v mestecku Breil sur Roya, do nehoz ustily dva tunely – jeden do francie a druhy do italie, my zacali splhanim primo nad nima – tudiz po hranici primo na jih.

Breil sur Roya
Breil sur Roya

Dalsim cestovnim prespanim byl bivak pod mesteckem na spicce kopce – Piene Haute, kdy pod nama celou noc behala divoka prasata, nad nama se po bezmracne obloze vznasel mesic a rano pred nama byl takovyto vyhled.

Ranni vyhled ze spacaku
Ranni vyhled ze spacaku

Potom uz jen sesup do francie olivovyma sadama, kde byl obcas nejakej fikovnik, takze si clovek mohl dat do nosu energii zdarma :-).

Francouzsko-italska hranice
Francouzsko-italska hranice

a predevsim celoodpoledni naadamovska koupacka (a prani pradla) pobliz Olivetta san Michele, ktere predchazelo dukladne pivkovani tamtez.

Koupani a prani pradla u Olivetty
Koupani a prani pradla u Olivetty

Potom opet hruzny vystup o cca kilometr vys, kde melo bejt nocovadlo, protoze se zacaly stahovat mracna. Nocovadlo bylo zamcene, ale melo aspon verandu, takze se dalo pred destem skryt (aspon castecne – ja travil noc s nohama v pytlu na odpadky :-D.

Francie u nohou
Francie u nohou

Za zminku tu stoji vesnicka Castellar, opet na kopci, kde jsme meli v planu poobedvat, ale nakonec jsme jen vyfotili par kocek, ulicek, dali pivko a spechali dal.

Ulicka v Castellar
Ulicka v Castellar

Rano opet sesup, tentokrat az k morske hladine a byl z celeho vyletu asi nejnarocnejsi, protoze vecerni chozeni po monaku bylo velice bolestive, takze jen snaha o nejakou kesku (opet nekorunovana uspechem), predrazeny pivko a jizda do Nice – konecne do hostelu.

Monte carlo - pristav
Monte carlo - pristav

Pesi vyprava byla tedy rozdelena na tri dny a trasa je zhruba nasledujici, muzu s klidnym svedomim doporucit (trasa je priblizna, protoze na hranici nejak nesedi mapove podklady googlu a na konci jsem se v tom bludisti trochu zamotal :-)):

Trasa na Everytrail

A potom uz nasledovalo – kdo to uhodne? Spravne, Saint tropez :-). Bylo tam mrte cechu – takovych tech s bilyma polama s malyma krokodylama. Zatim to k uhodnuti je, ale jak to dopadne? Cetnicka stanice je druhy ze dvou poslednich stojicich baraku na one slavne ulici, kolem jsou jamy az do pekel, takze se tam asi budou stavet nejake vyskace.

Cetnicka stanice
Cetnicka stanice

Zabrali jsme fajnovou plaz za mestem, kousek za hrbitovem a divili se mnozstvi zivota v mori – chobotnice, mraky obrovskych ryb… Kousek odtud jsme si udelali z jedne louky i hotel na dva dny a jen tak se proste flakali a slunili se :-).

Plaz pobliz spaciho fleku
Plaz pobliz spaciho fleku

No a tim se da vylet povazovat za ukonceny, protoze bohuzel nastal cas navratu. Takze zpatky pres Nice do Breil sur Roya, kde jsme se mohli naposledy pokochat kopci, do kterych jsme pred nekolika dny vyrazeli a potom trada na Cuneo, Torino a Milano a nasledujiciho dne z Bergama domu – ja do Blavy a kubas do Stockholmu. Toz pekne to bylo, ale brutalne kratke! Kopce na hranicich francie a italie bych si dal zas – a to tak, ze poradne!