29 Eylül 2008 Pazartesi

Sample Multithreaded Mailing Application

This Windows application uses multithreading capabilities of VB.NET to realize a mailing application project. You can use to learn the multithreading working style. Application seems like this (Bu Windows uygulaması, bir mailing projesini gerçekleştirmek için VB.NET'in çokkanalılık özelliklerini kullanmaktadır. Bu uygulamanın kodlarını inceleyerek, çokkanallı uygulama geliştirmeyi öğrenebilirsiniz. Uygulama şuna benziyor:):

Download Threading.zip



Main code (Form1.vb):



Public Class Form1

Public Stopped As Boolean = False

Public MaxThreadCount As Integer = 10

Public PostCount As Integer = 20

Public PostSent As Integer = 0

Public AssignedJob As Integer = 0



Public Status As String = "Ready"

Public Threads As IList(Of System.Threading.Thread) = New List(Of System.Threading.Thread)

Public MessageSenders As IList(Of MessageSender) = New List(Of MessageSender)



Sub Logging(ByVal text As String)

lstLog.Items.Add(Now.ToLongTimeString + ": " + text)

End Sub



Sub SenderThreadOnFinish(ByVal JobInfo As JobInfo)

PostSent = PostSent + 1

End Sub



Sub AssignJob(ByVal ThreadIndex As Integer)

MessageSenders.Item(ThreadIndex).JobInfo.PostIndex = AssignedJob

If Threads.Count - 1 < ThreadIndex Then

Threads.Add(New System.Threading.Thread(AddressOf MessageSenders.Item(ThreadIndex).Send))

Else

Threads.Item(ThreadIndex) = New System.Threading.Thread(AddressOf MessageSenders.Item(ThreadIndex).Send)

End If

Threads.Item(ThreadIndex).Start()

AssignedJob = AssignedJob + 1

Logging("Thread" + ThreadIndex.ToString + " sending post#" + AssignedJob.ToString)

End Sub



Private Sub btnStart_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStart.Click

Dim ThreadIndex As Integer



Status = "Running"

MaxThreadCount = nmrMaxThreadCount.Value

PostCount = nmrPostCount.Value

PostSent = 0

AssignedJob = 0

lstStatus.Items.Clear()

lstLog.Items.Clear()



'Initialize the status listbox

Logging("Threads are being created...")

For ThreadIndex = 0 To MaxThreadCount - 1

MessageSenders.Add(New MessageSender)

MessageSenders.Item(ThreadIndex).JobInfo.ThreadName = "Thread" + ThreadIndex.ToString

MessageSenders.Item(ThreadIndex).JobInfo.ThreadIndex = ThreadIndex

AddHandler MessageSenders.Item(ThreadIndex).Finish, AddressOf SenderThreadOnFinish

lstStatus.Items.Add("Thread" + ThreadIndex.ToString + ": Ready")

Next



Logging("Threads are being checking to assign job...")

ThreadIndex = 0

While AssignedJob < PostCount

If MessageSenders(ThreadIndex).JobInfo.ThreadStatus = "Ready" Then

AssignJob(ThreadIndex)

End If

If ThreadIndex = MaxThreadCount - 1 Then

ThreadIndex = 0

Else

ThreadIndex = ThreadIndex + 1

End If

Application.DoEvents()

End While



Status = "Ready"

Logging("Mailing have completed")

End Sub



Private Sub tmrThreadStatus_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tmrThreadStatus.Tick

Dim ThreadIndex As Integer = 0

For ThreadIndex = 0 To Threads.Count - 1

lstStatus.Items(ThreadIndex) = "Thread" + ThreadIndex.ToString + ": " + MessageSenders(ThreadIndex).JobInfo.ThreadStatus

Next

End Sub

End Class





Public Class MessageSender

Public JobInfo As JobInfo = New JobInfo

Public Event Finish(ByVal JobInfo As JobInfo)

Public Sub Send()

JobInfo.ThreadStatus = "Running"



Dim SmtpClient As System.Net.Mail.SmtpClient = New System.Net.Mail.SmtpClient("0.0.0.0")

Try

Dim Message As New System.Net.Mail.MailMessage("from@example.com", "to@example", "Hi Esref", "Please let me know, when you read the this message.")

SmtpClient.Credentials = New System.Net.NetworkCredential("username", "password")

SmtpClient.Send(Message)

Catch e As Exception

Console.WriteLine(e.Message)

End Try



RaiseEvent Finish(JobInfo)

JobInfo.ThreadStatus = "Ready"

End Sub

End Class



Public Class JobInfo

Public ThreadName As String

Public ThreadIndex As Integer

Public ThreadStatus As String = "Ready"

Public PostIndex As Integer

End Class



18 Eylül 2008 Perşembe

LiveCycle Workspace ekranında "ALC-WKS-007-040" hatası çıkıyor ve form açılmıyor

LiveCycle Workbench ile bir süreç geliştirdiniz. LiveCycle Workspace ekranını kullanarak formu açmaya ve kullanmaya çalıştınız fakat şöyle bir hata mesajı çıkıyor, form açılmıyor:

"An error occurred creating the form (task 2022, form 0). (ALC-WKS-007-040)"

Sistem LiveCycle Designer ile hazırladığınız formu dönüştüremiyor demektir (render). Bu sorunun olası iki nedeni:

1) LiveCycle Workbench'te form input değişkenini xfaForm yapmayı unuttunuz. Aşağıda, LiveCycle Workbench ekranında düzgün çalışan bir formun değişken ayarı görülebilir:




2) PDF formunu hazırlarken, formun tipini Dynamic XML PDF form yapmayı unuttunuz. Bu ayarı yapmak için, formu LiveCycle Designer'da açın. Şu menüyü açın:


File > Form Properties > Preview

...açılan penceredeki "Preview Adobe XML Form as" listesinden "Dynamic XML Form" seçin.

Formu PDF olarak masaüstünüze farklı kaydedin. Daha sonra LiveCycle Workbench'te Resources kısmına bu dosyayı sürükleyip bırakın. Artık formu LiveCycle Workbench'te input form değişkeni olarak kullanabilirsiniz.

Bu şekilde ayarlarınızı gözden geçirdiğinizde form yüksek ihtimalle açılacaktır.

11 Eylül 2008 Perşembe

LiveCycle Designer'da FormCalc ile HTTP Get yapmak ve XML yüklemek

PDF formlarda dışarıya bilgi göndermek veya bilgi almak için bir çok yöntem mevcuttur. Bu yöntemlerden bazıları Reader Extensions lisansı gerektirir. Biz burada, ek lısans gerektirmeyen, PDF'in temel dili olan FormCalc ile birlikte dahili olarak gelen HTTP Get/Post tekniğine değineceğiz.

Akıllı PDF formları, kullanıcının girdiklerini teyit etme özelliğine sahiptirler. Böylece toplanan verilerin doğruluk oranı artar. LiveCycle Designer ile hazırladığınız böyle bir formda dışarıdan bilgi yüklemeye ihtiyacınız olacaktır. Örneğin, girilen müşteri numarasını doğrulamak gibi. Böyle bir durumda merkez sisteme bağlanmak için kullanabileceğiniz yöntemlerden bazıları şunlardır:

* Doğruda veritabanına bağlanmak (Reader Extensions ek lisans alınması gerekir)
* Web servise bağlanmak (Reader Extensions ek lisans alınması gerekir)
* HTTP Get ile internetten bilgi çekmek. (Hiçbir ek lisans gerektirmez)

Biz bu yazımızda HTTP Get yöntemini kullanacağız. Müşteri numarası kutusunun yanına eklediğiniz düğmenin"click" event'ine FormCalc olarak şöyle bir kod yazın:

var xmlCustomer = Get(concat("http://www.example.com/bilgi.cfm?musteriNumarasi=", cust_no.rawValue)) xfa.datasets.data.loadXML(xmlCustomer, 1, 1)

Bu kodu kendi ihtiyaçlarınıza göre şekillendirmeniz gerekecektir. İlk satırdaki kodla, formdaki "cust_no" alanına girilen müşteri numarası HTTP Get ile bir web sayfasına gönderiliyor ve dönen XML metni "xmlCustomer" değişkenine aktarılıyor. İkinci satırdaki kodla, XML metni forma yükleniyor. Tıpkı LiveCycle Designer'daki Data View sekmesindeki "sample XML" yüklemek gibi. İkinci satırdaki bu kod sayesinde LiveCycle Designer XML'deki tüm bilgileri formdaki ilgili kutulara otomatik doldurulacaktır. Fakat formdaki alanlarınızın Binding'i "Normal" olmalıdır.

"bilgi.cfm" isimli web sayfasını biz ColdFusion ile geliştirmiştik. Geliştirdiğimiz kodu aşağıdaki görüntüde görebilirsiniz. LiveCycle Designer'ın HTTP Get ile URL'den gönderdiği "musteriNumarasi" isimli değişkeni veritabanına bağlanmak için kullandık:



Müşterinin bilgilerini veritabanından çekip XML olarak geri döndürüyorduk. XML'i aşağıda görebilirsiniz. XML'den de anlaşılacağı üzere, alanlarımız, cust_info isimli bir "subform" içerisindeydi:






Bizim böyle bir yönteme, bir banka için geliştirdiğimiz kredi başvurusu formunda ihtiyacımız olmuştu. LiveCycle Designer'da çalışırken aldığımız ekran görüntüsünü aşağıda gönderiyoruz. Faydası olabilir:

01 Eylül 2008 Pazartesi

LiveCycle Process Management ile veritabanına bağlanmak

Bu yazımızda, LiveCycle Process Management ile bir süreç yürürken sunucu tarafında SQL Server veritabanına bağlanmaya değineceğiz.

LiveCycle Process Management ile birlikte gelen Foundation servisleri arasında çok sayıda özellik vardır. Bizim burada ihtiyacımız olan servisin adı "JDBC"dir. Bu servisin çalışabilmesi için LiveCycle sunucu tarafında ayarlamalar yapılması gerekmektedir. Aşağıda bunları da anlatıyoruz.

1)
LiveCycle Process Management ilk kurulduğunda varsayılan olarak MySQL ve Oracle veritabanlarına bağlantı için hazır gelir. JBoss'a SQL Server'ın JDBC sürücüsü kurulduğunda bağlantı mümkün hale gelecektir. Öncelikle SQL Server JDBC sürücüsünü Microsoft'un sitesinden indiriniz:

http://msdn.microsoft.com/en-us/data/aa937724.aspx

2) Sıkıştırılmış dosya içerisindeki "sqljdbc.jar" dosyasını sunucuda şu klasöre koyunuz:

C:\Adobe\LiveCycle8.2\jboss\server\all\lib

3) Sunucuda şu adreste yeni bir XML dosya oluşturun:

C:\Adobe\LiveCycle8.2\jboss\server\all\deploy

4) XML dosyasının adı önemli değil. Örnek bir isim:

C:\Adobe\LiveCycle8.2\jboss\server\all\deploy\mssql-ds.xml

XML dosyasını değiştirdiğinizde LiveCycle otomatik olarak yeni ayarları kullanmaya başlayacaktır. XML dosyası için örnek bir içeriğin görüntüsü şöyledir:




5) Dosyayı yeni oluşturduğunuz için JBoss'u yeniden başlatınız.

6) Process'inizde veritabanı bağlantı servisi kullanınız. Örneğin, process'in bir aşamasında veritabanına kayıt eklemek istersek şu servisi kullanabiliriz:

Services > Foundation > JDBC > Execute SQL Statement

Örnek bir kullanım: