13 Temmuz 2012 Cuma

Sadece Kulağıma Küpe Olsun Diye...

DRY, yani Don't Repeat Yourself! Kendini tekrarlama! Her konuda, hatalarda olduğu gibi çözümlerde de. Az önce çok daha önceden karşılaştığım bir problem ile tekrardan cebelleşmek zorunda kaldım. Demek ki neymiş? Bir yerlere yazmak gerekliymiş. Kafaya yazmaktansa kağıda, daha iyisi bloğa yazmak en güzeli. Sonuçta beyin bedava derler ama kazın ayağı biraz farklı.

Her neyse problem şuydu: Basic Authentication yapmak istiyoruz. Malzemeler Weblogic ve Spring Security. Konfigürasyon falan herşey tamam. Bi deneyelim bakalım çalışıyor mu diye Firefox'un modify headers'ine Basic ABCDE== şeklinde Authorization header'mizi de ekledik. O da ne? Username ve password soruyor. Soran kim? Weblogic! Ne alaka? Herif Deli Dumrul gibi tutmuş köprünün başını. Ne geleni geçiriyor ne gideni.

Peki ne yapalım? En iyisi weblogic'e bu davranışının yanlış olduğunu hatırlatalım. Bunun için .../Middleware/user_projects/domains/[benim_domain]/config altındaki config.xml'i açalım ve <security-configuration> taginin içerisine şöyle bişey ekleyelim.

<enforce-valid-basic-auth-credentials>false</enforce-valid-basic-auth-credentials>

Sonra da Allah'ın emri, bi restart edelim. Çalışmazsa getirin mal bizim :)

9 Ocak 2011 Pazar

Manipulating Microsoft Docx Files With Docx4j

Last week, I witnessed complaints of one of my colleagues who is responsible for testing of our current project. She was yelling because she didn't want to write no more documents. I thought that, she hates documentation. Me too. I completelly share same ideas with her. I know lots of people agree with me. And in addition, I also hate to do something again and again. To deal with usual and banal activities is so boring that I always try to kepp away. In my opinion, documents and documentation take place at the center of boring activities of software development processes.

So, I thought whether it is possible or not to make the documents be written programatically. Why not? Most of our documents are based on MS Word and There are several libraries to write MS Word documents. I came across docx4j while I was looking around these libraries. Docx4j stands out with its solutions on the latest version (currently 2007) of MS Word. To investigate its structure, let's go into details by creating a new docx file. Open MS word, write your name and save it. Then, change the file extension from docx to zip and extract it with your favorite zip program. You see a directory hierarchy like this:

Doc1
_rels
.rels
docProps
app.xml
core.xml
word
_rels
document.xml.rels
theme
theme1.xml
document.xml
fontTable.xml
settings.xml
styles.xml
webSettings.xml
[Content_Types].xml

As you can see, there are just directories and some xml files. Open word/document.xml with your favorite xml editor and find your name in it. As you will see, your name is between and tags. We can say that docx file format is a zipped directory structure which contains some XML files, and these XML files hold information typed and saved by you. So we can extract and parse these XML files to gather content of the document. To change this content, we can also edit these files and package again. Docx4j does these for us with assistance of JaxB.

To show how Docx4j works, we will create a sample project. In this project, assume that you have a son and intend to throw a party in orde to celebrate your little son's birthday. To invite your friends, you design an invitation card template. In this template you leave some parts as blank and want to fill in the blanks with custom information. Because you don't want to prepare another template for next year.

To implement this dream, we will start by creating a project. I prefer to use Maven (http://maven.apache.org/) to create project structure, because it's easy. I will skip creation steps of project, because they are irrelevant. If you want, you can refer to maven documentation to see these steps. I'll give you a link to download whole project at the end of this document.

Anyway, I created a project and a template for invitation card. When creating the template, I left some placeholders to name blank parts of the template. Let's create a class named as Invitation. This class will be responsible for loading the template, replacing placeholder with some real values and saving the produced file as another word document. We will be giving placeholder values in a map, template file path and output directory as constructor arguments:

public class Invitation {

private Map templateProperties;
private String templateFilePath;
private String outputFolderPath;

public Invitation(Map templateProperties, String templateFilePath,
String outputFolderPath) {
this.templateProperties = templateProperties;
this.templateFilePath = templateFilePath;
this.outputFolderPath = outputFolderPath;
}
...

First we should load the template:

WordprocessingMLPackage template = WordprocessingMLPackage
.load(new File(templateFilePath));

By doing this, we created template object, a WordprocessingMLPackage instance. WordprocessingMLPackage is a docx package and holds whole Word document.

Second, we should fill in the blanks. We should replace the placeholders with their relevant real values given in a map as a constructor argument. To do this, retrieve the "w:t" nodes via xpath and change their values:

private void replacePlaceholders(WordprocessingMLPackage targetDocument,
String nameOfTheInvitedGuest) throws JAXBException {

List texts = targetDocument.getMainDocumentPart()
.getJAXBNodesViaXPath(XPATH_TO_SELECT_TEXT_NODES, true);

for (Object obj : texts) {
Text text = (Text) ((JAXBElement) obj).getValue();

String textValue = text.getValue();
for (Object key : templateProperties.keySet()) {
textValue = textValue.replaceAll("\\$\\{" + key + "\\}",
(String) templateProperties.get(key));
}

text.setValue(textValue);
}
}

And finally, we should save the file:

template.save(new File(outputFolderPath + "/"
+ nameOfTheInvitedGuest + ".docx"));

That's all. We opened a file, traversed its content with Xpath, changed some parts and saved it. It was a very simple example. I intended to give you a point of view about docx file format and Docx4j's functionality. As you saw, docx file is a package of some parts. In Docx4j this package can be loaded as a WordprocessingMLPackage instance. If you go into deeper, you will see that WordprocessingMLPackage class has a main document part and an optional glossary document part. We obtained main document part and picked up text nodes via XPath and changed them. We didn't do anything about other MS Word concepts such as numbering, styles and images. They are also another parts and can be reached by WordprocessingMLPackage. If you deal with these parts, you will see that, you need more information about open xml formats. You can also find more information on http://dev.plutext.org.

In conclusion, upon my first impression about Docx4j, it is a useful library for processing MS Word documents. However, you should be familar with open xml formats in order to perform more complex works. It gives a flexible way to edit XML content with JaxB although this flexibility comes with a bit complexity. As the last word, I want to congratulate Plutext team, creators of Docx4j.

Click here to download sample project.

29 Ekim 2009 Perşembe

Server-centric, Client-centric. Peki ya Developer-centric?

Uzun zamandır tartışma konusuydu sunucu ya da istemci odaklı RIA (Kallavi İnternet Uygulamaları) çözümlerinden hangisinin daha etkin olduğu. Kimine göre istemci odaklı olanlar daha iyi, kimine göre ise sunucu odaklı olanlar. İtinayla tartışılır...

Peki farkı neydi bu ikisinin? İstemci odaklı çalışanlar uygulama ekranlarında yapılan alengirli hokus-pokus hareketlerini (ki kullanıcıyı cezbeden çok güzel hareketlerdir bunlar) javascript falan kullanarak kullanıcının tarayıcı uygulaması (IE, Firefox vs.) üzerinde çalıştırırlar. Ha böyle olunca ne olur? Ufak tefek kıytırık getir-götür işleri için sunucu tarafı boşuna yorulmaz. Kullanıcının bilgisayarının da çorbada bir nevi tuzu olur.

Amma ve lakin bu işin bir de baş ağrıtıcı, mide bulandırıcı bir yönü vardır. Bu javascript denen dil çok karmaşık şeylerden bahsederse saçmalar, tarayıcılar söylemek istenenden farklı anlamlar çıkarabilir. O zaman da siz "akım" kodlarsınız kullanıcıya "b.kum" olarak gider, ayıp olur. Bunu önlemek için de tarayıcının suyuna gidilir, anladığı dilden konuşulur. Böyle olunca da buna uygun RIA'yı geliştirmek üstün nitelikler ve çelik gibi bir sinir sistemi gerektirir. Oluşan javascriptin WTFs/min oranı yüksektir. Bu ölçümün nasıl yapıldığından sonra bahsederim.

Bu işi başaran babayiğitlere örnek vermek gerekirse en başta bir Google iştiraki olan GWT gelir. GWT ile kodladığınız java kodları Google'ın yeminli tercümanları tarafından Javascript kodlarına tercüme edilerek tarayıcıya gönderilir. Bilindiği üzere bilgisayarlar "aptal" makinelerdir. Yani ne yapacağını inceden inceye söylemek gerekir. Yoksa şaşırıp afallar, salak. Madem ki serde istemci odaklı olmak var, o zaman çalışacak kodu tümüyle kullanıcının makinesine göndermek gerekli. Bu da sunucudan istemciye giden veri trafiğini artırır. Her ne kadar teknoloji ilerlemiş, fiber optik kablolar falan ayağa düşmüş olsa da bilinçli yazılımcı donanıma güvenerek iş yapmaz, (Hacettepe Bilgisayar Müh. mezunları bilirler, Mustafa hoca veri yapıları dersinde sineğin yağını çıkarır, posasını da geri dönüşüme gönderirdi. Sınav sorularında "yeni değişken tanımı yapmaksızın" ibaresi saç baş yolduracağına delalettir) istemciye göndereceği kodu kısa tutmaya çalışır. Bilgisayarın kitabını yazmış olan Tanenbaum amcamız 'As I did 20 years ago, I still fervently believe that the only way to make software secure, reliable, and fast is to make it small.' demiş dilinden anlayana. Kısacası "kısa kesin, Aydın havası olsun" demiş. Neyse gene çok dağıttık, toplayalım: istemci odaklı RIA çözümleri tarayıcıya çok yüklenirler. Bu da istemci tarafını şişirir. Bu da muhtelif meclislerde yazılımınızın yavaşlığının mevz-u bahis edilmesine sebep olur.

Gelgelelim, sunucu odaklı RIA çözümlerinde yukarıdakilerin hiç biri olmaz. Bunun yerine kullanıcılar Lütfen Bekleyiniz..., Processing..., Loading..., Lan iki dakka sabret... gibi AJAX sonrası dilimize pelesenk olmuş nevi şahsına münhasır deyimlerimizle sıkça aşina olurlar. Çünkü istemci tarafı tembeldir ve herşeyi sunucudan bekler. Tabiri caizse yerinden kalkıp mutfaktan su almak yerine yan odada ütü yapan karısından su isteyen tembel kocalar (aaa çok ayıp!) gibidir. Kadıncağız söylene söylene suyu getirir, bazen de sabrın sınırı aşılır, küser cevap vermez. (Ping! cevap yok!) Çünkü aynı anda bir yandan bebek altına yapmıştır, temizlenmesi için zırlar durur, küçük çocuk acıkmıştır, büyük olanın ise yarına yetişecek bir ödevi mutlaka vardır. Apache kabilesinden Wicket da bu mantıkla çalışır.

Bir "made in China" RIA çözümü olan ZKyı da sunucu odaklı bilirdik. Fakat Çan, çin çun ve Chen amcalar şu sıralar çıktım çıkacam (release candidate - RC) diyen 5. sürümde yukarıdaki yaman çelişkiyi farketmiş olacaklar ki orta yolu bulmuşlar ve az biraz kılıbıklaşarak, geliştiricileri de düşündüklerini beyan ederek developer-centric bir RIA yaklaşımı ortaya atmışlar. Server-Client Fusion diye adlandırdıkları bir yapı ile turnayı gözünden vurmuşlar. İşin detayına girip de kafa karıştırmaya hiç niyetim yok, merak eden zkoss.org'dan kendisi bakar. Hazır bakmışken ajax-as-a-service kısmına da bakar, bence. Zaten bileşen zenginliğiyle ön plana çıkan ZK'ya bu iki işlevsellik tuz-biber olmuş. (Diğer RIA çözümlerine de kapak olmuş da denebilir.)

Tadından yenir mi yoksa yanında mı yatılır bilmem ama üzerine tatlı niyetine güzel bir haber daha vereyim: Lisanslamayı değiştirmişler. Artık bundan böyle GPL (Kimine göre GPL bir virüstür, bulaştığı yazılıma kendini kopyalar ve yayılır.) değil, LGPL. Yani bundan böyle binbir emekle yazdığınız kodları sırf ZK kullandığınız için cümle aleme mal etmek zorunda değilsiniz. Bu da günün güzel haberi olsun.

Benden bu kadar, yorumlarınızı bekliyorum. Bundan önce bi kaç kere daha farklı konularda blog yazdım. Sonra da bi kaç kere okudum, beğenmedim sildim. Üsluba bir türlü karar veremedim, çünkü. Yarın biraz daha ağır takılayım dersem belki bunu da silerim, belki de silmem. Herkesin 29 Ekim Cumhuriyet Bayramı kutlu olsun. Ne mutlu TÜRK'üm diyene!


* Bu arada WTFs/min yöntemi (What the fucks per minute): Yazılmış kod parçası başka bir yazılımcı ile beraber kapalı bir odada başbaşa bırakılarak yazılımcının kodu incelemesi istenir. Kapının dışından bir gözlemci kulağını kapıya dayar ve içeriden gelen "What The Fuck" ünlemlerini sayar. Elde edilen sonuç incelenen kod kalitesi açısından oldukça belirleyicidir :)