Run seam 2.2 with jdk 7 and jboss eap 6.2 (as 7.3)

1393 / 6 / 26

Posted by omidp under Tech Stuff
0 نظرات

جی باس یا شاید دیگه وایلد فلای در حال حاضر یکی از پر استفاده ترین اپ سرورهای متن باز جاوا است که تغییرات زیادی از نسخه ۷ به بعد در بر داشته و اگه شما جزو اون دسته از کاربران فریم ورک سیم ۲.۲ هستید که می خواهید نرم افزار خود را ارتقا دهید تا امکانات بیشتری به آن مثل وب ساکت ، استفاده از ان آی او برای کار با فایل سیستم و غیره ، راحتر اضافه کنید وقت آن رسیده که از جاوا ۷ و جی باس ۷.۳ استفاده کنید . برای اجرای پروژه سیم ۲.۲ بر روی جی باس ۷.۳ مراحل زیر را دنبال کنید

جی باس ۷ به بعد از سیستم classloading ای بی نظیر و جالب استفاده می کند که شما می توانید ماژول های مختلف از یک فریم ورک را با اسلات های مختلف در یک پروژه تنظیم کنید که جلوتر با هم خواهیم دید

ابتدا نیاز به تغییر چند فایل کانفیگ در پروژه است

خط زیر را به فایل persistence.xml اضافه کنید

<property name="jboss.as.jpa.providerModule" value="org.hibernate:3" />

در ear فایل شما داخل فولدر META-INF فایل jboss-deployment-structure.xml را بسازید

<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.0">
      <deployment>
		  <exclusions>
              <module name="org.hibernate" slot="main"/>
            </exclusions>  
            <dependencies>  
              <module name="org.apache.log4j" export="true"/>  
              <module name="org.hibernate" slot="3" export="true"/>  
              <module name="org.dom4j" export="true"/>  
              <module name="org.apache.commons.logging" export="true"/>  
              <module name="org.apache.commons.collections" export="true"/>  
              <module name="javax.faces.api" slot="1.2" export="true"/>  
              <module name="com.sun.jsf-impl" slot="1.2" export="true"/>  
            </dependencies>  
      </deployment>  
      <sub-deployment name="omidbiz.war">   
          <exclusions>  
              <module name="javax.faces.api" slot="main"/>  
              <module name="com.sun.jsf-impl" slot="main"/>  
            </exclusions>  
            <dependencies>  
              <module name="javax.faces.api" slot="1.2"/>  
              <module name="com.sun.jsf-impl" slot="1.2"/>  
            </dependencies>  
      </sub-deployment>   
     </jboss-deployment-structure>  

این فایل داستان زیادی در دل دارد اول به جی باس میگه که از jsf ۱.۲ استفاده کند چراکه پیش فرض جی باس ۷ به بالا جی اس اف ۲ است و سیم ۲.۲ از جی ای اف ۱.۲ استفاده می کند دوم اسلات هایبرنیت ۴ که باز هم پیش فرض جی باس است را از کار میندازد و هایبرنیت اسلات ۳ را فعال می کند که باید به جی باس معرفی شود و بقیه dependency ها هم مشخص است .

مرحله بعد تنظیمات EJB

فایل component.xml

تعریف JNDI برای EJB در هر اپ سروری متفاوت convention در جی باس های قدیمی به این صورت بود

 earName/#{ejbName}/local

در نسخه جدید تغییر کرد و باید آن را به صورت زیر عوض کنید

<core:init jndi-pattern="java:app/earName/#{ejbName}" debug="true"/>
<component class="org.jboss.seam.transaction.EjbSynchronizations" jndi-name="java:app/jboss-seam/EjbSynchronizations"/>
    <component class="org.jboss.seam.async.TimerServiceDispatcher" jndi-name="java:app/jboss-seam/TimerServiceDispatcher"/>
<persistence:managed-persistence-context
		auto-create="true" name="entityManager" persistence-unit-jndi-name="java:/omidbizEntityManagerFactory" />

تنظیمات دیتا سورس

در این پست توضیح داده شده

معرفی اسلات ۳ هایبرنیت

همانطور که گفتم کلاس لودینگ استثنایی جی باس ۷ به شما این امکان را می دهد تا نسخه های مختلف از یک فریم ورک را بصورت ایزوله برای پروژه های خود استفاده کنید یعنی در یک جی باس دو پروژه داشته باشید که یکی از هایبرنیت ۴ استفاده می کند و دیگری از هایبرنیت ۳ . برای اضافه کردن هایبرنیت ۳

در پوشه ماژوال فولدر org/hibernate فولدری با نام 3 بسازید

در این فولدر فایلی به نام module.xml ساخته و جر فایل های هایبرنیت را به آن اضافه کنید

<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.0" name="org.hibernate" slot="3">
    <resources>
        <resource-root path="hibernate-core.jar"/>
        <resource-root path="hibernate-commons-annotations.jar"/>
        <resource-root path="hibernate-entitymanager.jar"/>        
        <resource-root path="hibernate-annotations.jar"/>
        <resource-root path="antlr.jar"/>  
        <resource-root path="commons-collections.jar"/>  
        <resource-root path="dom4j.jar"/>  
        <resource-root path="javassist.jar"/>  
        <!-- Insert other Hibernate 3 jars to be used here -->
    </resources>
 
    <dependencies>
        <module name="org.jboss.as.jpa.hibernate" slot="3" optional="true" services="import"/>
        <module name="asm.asm"/>
        <module name="javax.api"/>
        <module name="javax.persistence.api"/>
        <module name="javax.transaction.api"/>
        <module name="javax.validation.api"/>
        <module name="org.infinispan"/>
        <module name="org.javassist"/>
        <module name="org.slf4j"/>
    </dependencies>
</module>

همه چیز آماده است پروژه سیم خود را اجرا کنید . توجه کنید که اگر از لایبرری جاوایی استفاده کردید فراموش نکید که آن را در پروژه قرار دهید یا به جی باس معرفی کنید برای راحتی کار بهتر است از maven استفاده کنید نسخه جدید سیم با می ون است اما اگر از نسخه قدیمی سیم می خواهید استفاده کنید می توانید از Jboss Seam 2.3 ALPHA استفاده کنید این همان نسخه سیم ۲.۲ مبتنی بر می ون است

dogfooding

1393 / 6 / 22

Posted by omidp under General
2 نظرات

practice what you preach

پیام صادری در یکی از پست های بلاگش در مورد زامبی بودن ، نوشته ای منتشر کرد و در آن این جمله ذکر شده ، افراد متعصب یا همون زامبی ها فکر نمی‌کنند ، که با عث شد من این پست رو در جواب ایشون بنویسیم که شاید بهتر باشه قبل از قضاوت در مورد حتی زامبی ها از طرز تفکر زامبی وارشان مطلع شویم.

eating your own dog food

در دنیای تکنولوژی اصطلاحی وجود داره که در این پست راجع بهش توضیح می دم . قبلش یک مقدمه کوچکی مطرح کنم که

وقتی یک ابزار یا زبان برنامه نویسی را انتخاب می کنید ، در واقع شما فقط یک زبان وابزار را انتخاب نکرده اید بلکه یک فرهنگ با مجموعه ای از افکار متفاوت و انجمنی از آدم های مختلف را انتخاب کردید چراکه همین فرهنگ و طرز تفکر است که از شما یک مصرف کننده خوب یا عالی را میسازد . شما نحوه استفاده از ابزار را در جامعه ای که در آن هستید می آموزید .

برای روشن تر شدن موضوع اجازه دهید مثالی بزنم ممکن است در یک جامعه از چاقو برای بریدن طناب استفاده شود و در جامعه دیگر برای باز کردن طناب.

همانطور که در بلاگ گودزیلای وب فارسی گفته شد ( وب فارسی همین یه قلم و کم داشت فقط ) در عصری زندگی می کنیم که شرکت های بزرگ مثل اپل ، گوگل و خیلی های دیگه محصولات موازی زیادی تولید می کنند اما سوال اینجاست آیا گوگل برای تولید محصولات خود از محصولات اپل استفاده می کنه ؟ آیا شما می تونید فلسفه لینوکس رو درک کنید در حالی که از ویندوز استفاده می کنید ؟ به نظر من که منطقی نیست در واقع مفهوم داگ فودینگ در خارج از جامعه نرم افزاری خیلی آشنا نیست و به این نکته اشاره داره که اگر می خواهید کیفیت محصولی که تولید می کنید را بهبود دهید ، خودتان از آن محصول استفاده کنید.

البته شما نباید خودتان را فقط محدود به یک نرم افزار کنید و این خود نشاندهنده این است که هیچ تعصبی در کار نیست .

یعنی اگر شما مجله ای گردآوری می کنید که هدف آن ترویج لینوکس و نرم افزار آزاد است به هیچ وجه اشکالی نداره که از مجلات غیر آزاد ایده بگیرید اما اشکال داره که از ابزارهای غیر آزاد استفاده کنید . این دو مورد کاملا با هم متفاوت است.

خیلی نمی خوام مطلب رو کش بدم در آخر می خوام نتیجه گیری کنم که زامبی باشید

Pro NonPro Solar Solr

1393 / 6 / 9

Posted by omidp under General
4 نظرات

تقدیم به تمام کسانی که سولر را سولار تلفظ می کنند

حرفه ای می داند به خاطر چه چیزی بجنگد و بر سر چه چیزی سازش کند، غیر حرفه ای به خاطر چیزی که ارزش ندارد مبارزه میکند و آنجا که نباید سازش میکند

چند وقت پیش در یکی از گروه های جاوا ، مسئله ای در مورد تلفظ صحیح کلمه سولر مطرح شد و بحث بالا گرفت. نکته مهم تلفظ این کلمه نیست بلکه نحوه برخورد با این مسئله بود که برای من جالب است.

هر انسانی ممکن است خطا کند چراکه انسان ممکن الخطاست اما پافشاری و قبول نکردن اشتباه را می توان خامی و عدم پختگی گفت. توجه کنید منظورم از اشتباه تلفظ صحیح کلمه نیست بلکه نحوه برخورد با این مسئله است وقتی کسی به شما می گوید تلفظ این کلمه سولر است یک درصد احتمال دهید که ممکن است درست بگوید و از منابع معتبر مثل دیکشنری استفاده کنید تا مطمئن شوید حالا سوال من اینجاست وقتی شما به خودتان زحمت نمی دهید تا یک کلمه ساده را چک کنید چطور من به عنوان نیروی فنی به شما اعتماد کنم و کد افراد دیگر را به شما داده یا به شما اجازه کد نوشتن در برنامه ای که برای آن زحمت کشیده ام بدهم ؟؟

در جاوا صرف نظر از اینکه چه تکنولوژی هایی بلد هستید ، چک کردن رفرنس ایمپیلیمنتیشن و دیزاین پترن کاری ضروری است.

روش درست : شما می توانید یک لحظه شک کنید و بعد از اینکه مطمين شدید اینطور برخورد کنید تلفظ صحیح آن سولر است اما در فارسی سولار مصطلح است مثل خیلی از کلمات دیگر مانند سوکت و.. تا اینکه کینه به دل بگیرید و به خاطر رفتار یک نفر اعتبار شرکتی را زیر سوال ببرید

بارها شده در مصاحبه های مختلف افرادی بودند که دانششان از من بیشتر بوده اما من بجای اینکه آن ها را سرزنش کنم سعی می کنم دانش خود را ارتقا داده و همیشه از کسی که چیزی به من یاد می دهد متشکر هستم

اینکه بعد از گذشت چند هفته ، هنوز من رفرنسی برای حرف خودم چک نکرده ام تا به اشتباهم پی ببرم و شخص دیگری را سرزنش می کنم و سعی می کنم تا اشتباه خودم را به او تحمیل کنم نشاندهنده این است که نه تنها ،حتما شخصی باید بالا سر من باشد تا کار درست را به من گوش زد کند بلکه در کار تیمی هم هیچ وقت موفق نخواهم بود چراکه اگر در تیم حرفی زده شود و آن حرف برای من ناخوشایند باشد برای بقای تیم باید آن حرف را بپذیرم و این قابلیت را ندارم. منظور قابلیت گذشت است

در نهایت هم  همونطور که گفتم با چک کردن فونتیک در دیکشنری متوجه می شید که تلفظ صحیح Solar(Solr) همان سولر است که در فارسی سولار می گویند مانند lunar

http://www.oxfordlearnersdictionaries.com/definition/english/solar

Java Websocket Swing Client

1393 / 4 / 24

Posted by omidp under Code Snippet
0 نظرات

میشه گفت نسل بعدی اپلیکیشن های وب بعد از Ajax ، نرم افزارهای real-time است یکی از راه های پیاده سازی این نرم افزارها استفاده از وب سوکت است که در یکی از پست های قبلی به آن اشاره کردم.

در حال حاضر، در حال توسعه یک اپلیکیش جاوایی دسکتاپ swing هستم که نیاز دارد تا به عنوان کلاینت از طریق وب سوکت به سرور متصل شود برای اینکار پروژه ای بنام تایروس وجود دارد که در واقع Reference implementation وب سوکت است و با کد زیر به راحتی می توانید اینکار را انجام دهید.

ابتدا dependency تایروس را به پروژه خود اضافه کنید


			org.glassfish.tyrus.bundles
			tyrus-standalone-client
			1.7
		

package com.omidbiz.ws;

import java.io.IOException;
import java.net.URI;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import javax.websocket.ClientEndpointConfig;
import javax.websocket.ClientEndpointConfig.Configurator;
import javax.websocket.Endpoint;
import javax.websocket.EndpointConfig;
import javax.websocket.HandshakeResponse;
import javax.websocket.MessageHandler;
import javax.websocket.RemoteEndpoint.Basic;
import javax.websocket.Session;

import org.glassfish.tyrus.client.ClientManager;

/**
 * @author : Omid Pourhadi omidpourhadi [AT] gmail [DOT] com
 */
public class WebSocketClient
{

    Basic basicRemoteEndPoint;

    public void connect()
    {
        try
        {
            final ClientEndpointConfig configuration = ClientEndpointConfig.Builder.create().configurator(new RemoteConfigurator()).build();
            ClientManager client = ClientManager.createClient();
            SocketEndPoint endPoint = new SocketEndPoint();
            client.connectToServer(endPoint, configuration, new URI("ws://127.0.0.1:8080/websocket"));
            basicRemoteEndPoint = endPoint.getRemoteEndPoint();

        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    public void sendMessage(String message) throws IOException, InterruptedException
    {
        basicRemoteEndPoint.sendText(message);
    }

    // Endpoint definition
    private class SocketEndPoint extends Endpoint
    {
        private Session sess;

        @Override
        public void onOpen(Session sess, EndpointConfig ec)
        {
            this.sess = sess;
            this.sess.addMessageHandler(new MessageHandler.Whole()
            {

                @Override
                public void onMessage(String message)
                {
                    System.out.println("message broadcast from server : " + message);
                }

            });
        }

        public Basic getRemoteEndPoint()
        {
            return sess.getBasicRemote();
        }

    }

    // Websocket Configuration
    private class RemoteConfigurator extends Configurator
    {

        @Override
        public void beforeRequest(Map> headers)
        {
            //everything you need to send as request header
        }

        @Override
        public void afterResponse(HandshakeResponse hr)
        {

        }

    }

}

Recursively throgh Java nio

1393 / 4 / 19

Posted by omidp under Code Snippet
0 نظرات

public static void main(String[] args) throws IOException
    {
        Path start = Paths.get("/home/omidp/persiangig/");
        Files.walkFileTree(start, new SimpleFileVisitor()
        {
            @Override
            public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException
            {
                System.out.println(dir);
                return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException
            {
                System.out.println(file);
                return FileVisitResult.CONTINUE;
            }
            
            
        });
    }
    
 

Persian Language Detection in Tika

1393 / 4 / 1

Posted by omidp under Tech Stuff
1 نظرات

آپاچی تیکا یکی از جذاب ترین پروژه هایی است که تا به حال کار کرده ام . این پروژه امکانات زیادی دارد که یکی از آن ها امکان شناسایی زبان بر اساس محتوای فایل است . در این پست نحوه اضافه کردن زبان فارسی به تیکا را توضیح می دهم .

ابتدا اجازه دهید نگاهی کلی به آناتومی شناسایی زبان توسط این پروژه بندازیم . تیکا برای شناسایی یک زبان جدید از پروفایل استفاده می کند که این ساختار پروفایل ، وابسته به الگوریتم خاصی است . در واقع پروفایل مجموعه ای از لغات خاص در آن زبان است که corpus نامیده می شود .

سوال اولی که باید به آن پاسخ داد این است که چگونه یک توسعه دهنده شناسایی زبان یا ابزارهای Natural Language Processing می تواند منبع خوبی از corpus پیدا کند ؟

برای زبان فارسی این منبع وجود دارد که خیلی کامل است. شما می توانید آن را از مجموعه همشهری دانشگاه تهران تهیه کنید اما چون در ایران کسی اعتقادی به مفهوم آزاد ندارد استفاده از این منبع دست شما را می بندد البته اگه بتونید رمز فایل های زیپ رو ازشون بگیرید. اما نگران نباشید هنوز آدم هایی هستند که این مفهوم را درک می کنند با تشکر از بهداد اسفهبد فایل زیر همین کار را برای شما می کند

دانلود فایل Persian corpus

از اونجایی که شما در ایران کار می کنید و جاوا کار هستید حتی یک لحظه هم فکر نکنید که می تونید فقط همین بخش از تیکا را خودتان به تنهایی بنویسید به این علت که تیکا علاوه بر الگوریتم پروفایل که بر اساس تکرار کلمات مشابه در جمله است از الگوریتمی بنام N-gram استفاده می کند که در حال حاضر که این مطلب رو می خونید مطمئنا نمی دونید این الگوریتم چیه !! برای کار با تیکا هم نیازی به دانستن آن نیست پس به توضیح این الگوریتم نمی پردازیم .

حالا که شما ، هم مجموعه کلمات فارسی دارید هم سورس های تیکا ، برای اضافه کردن زبان فارسی مراحل زیر را طی کنید

ایجاد فایل فارسی n-gram

java -jar tika-app-1.4.jar --create-profile=fa -eUTF-8 persian-words.txt

خروجی دستور بالا فایل fa.ngp است . این فایل را داخل ماژول tika-core در آدرس زیر قرار دهید

/src/main/resources/org/apache/tika/language

سپس زبان فارسی را به فایل tika.language.properties اضافه کنید و به همین سادگی یک زبان جدید به تیکا اضافه شد برای اینکه مطمئن شوید می توانید از فرمان زیر استفاده کنید

java -jar tika-app-1.4.jar --language http://www.ohchr.org/EN/UDHR/Documents/UDHR_Translations/eng.pdf
java -jar tika-app-1.4.jar --language http://www.ohchr.org/EN/UDHR/Documents/UDHR_Translations/prs.pdf

اگر از نسخه تیکا ۱.۶ به بالا استفاده می کنید نیازی به انجام این کارها نیست و زبان فارسی بطور پیش فرض در تیکا وجود دارد

Genymotion 2.2 VirtualBox 4.3.6 Fedora 20 For Android

1393 / 2 / 3

Posted by omidp under Tech Stuff
0 نظرات

توسعه در سیستم عامل لینوکس بسیار لذت بخشه و خیلی از ما علی رغم میل باطنی و اجباری که در کار با ویندوز وجود دارد ، همچنان دوست داریم خیلی از کارها را در لینوکس انجام دهیم در این پست نحوه اجرا کردن genymotion که یک ایمولاتور اندروید است و اتصال آن به سیستم عامل فدورا در یک VM دیگر را توضیح می دهم .

البته دلیل دیگر این است که genymotion بر روی توزیع لینوکس فدورا و ردهت در حال حاضر کار نمی کند

ابتدا genymotion را از سایت آن دانلود کنید

http://www.genymotion.com/

برای نصب ۲.۲ genymotion نیاز به Virtual Box دارید در اینجا از Vbox 4.3.6 استفاده شده . بنابراین قبل از آن vbox را نصب کنید . نصب vbox بر روی ویندوز بسیار ساده است . سپس توزیع لینوکس مورد نظر خود را به همراه ابزارهای توسعه اندروید بر روی vbox نصب کنید که من از فدورا ۲۰ استفاده کرده ام .

فایل نصب genymotion را اجرا ، دیوایس مورد نظر را اضافه کنید و آن را اجرا کنید با کلیک بر روی آیکون در صفحه اصلی IP آدرس آن را خواهید دید

تا اینجا که کار خاصی انجام نشده از اینجا به بعد شما وارد مسیر زیر شده و فرمان زیر را اجرا می کنید

cd $ANDROID_HOME/sdk/platform-tools ///home/omidbiz/adt/sdk/platform-tools
adb connect 192.168.56.101

و به همین سادگی شما می توانید توسعه خود را در لینوکس انجام داده و نتیجه آن را در ایمولاتور ویندوزی ببنید

new year

1393 / 1 / 3

Posted by omidp under General
0 نظرات

You can't live your life for other people. You've got to do what's right for you, even if it hurts some people you love.

سال ۹۲ هم به اتمام رسید و مثل هر سال در این پست یک جمع بندی از سال قبل رو می نویسم. اول از همه جمع بندی می کنم که سال قبل سال خوبی بود. از نظر کاری با تلاش های فراوان همکاران ، دوستان و اعضای گروه ( نه تیم ) توانستیم یک محصول تولید کنیم که در حال حاضر ۱۱۰۰۰ کاربر دارد .

cld.persiangig.com

بعلاوه بعد از مدت ها کمی وقت کردم اندروید کار کنم .

در سال جدید سعی می کنم برنامه ریزی نکنم چون هر وقت برنامه ریزی می کنی زندگی برنامه های دیگری برای شما دارد

Life is what happens to you while you're busy making other plans.

در سالی که گذشت خیلی وقت نکردم که بلاگ بنویسیم و کمی هم محتوای بلاگ از محتوای فنی فاصله گرفت اما امسال اگه بتونم سعی می کنم ویدیو های آموزشی اندروید روی سایت قرار بدم.

طبق معمول چند پروژه متن باز درست کردم که مهمترین آن ها می توان به آکسون اشاره کرد با تشکر از دوست و همکار خوبم

https://github.com/omidp/axon

شرکت در استارت آپ ویکند یکی از تجربه های جدیدی بود که در این سال داشتم . درست است که خیلی ها بصورت خانوادگی و فقط برای برنده شدن در آن شرکت می کنند و در آخر هم پروژه ای که سال ها روی آن کار کردند را به نمایش می گذارند که البته این کار به نظر من خوب نیست اما تجربه خوبی بود و برای راه اندازی یک استارت آپ ایده های خوبی بهم داد و چیزهای زیادی یاد گرفتم.

برخی از پست ها از سال قبل مونده که در سال جدید پست می کنم . در سال جدید تویتر منو فالو کنید به دلیل کمبود وقت قادر به نوشتن بلاگ نخواهم بود اما در مورد تکنولوژی های جدید و اخبار و اتفاقات حتما توییت می کنم

در آخر هم امیدوارم امسال سالی پر از شادی ، سلامتی و پول برای همه باشد مخصوصا برای خودم .

بانک سامان بانک هوشمند یا گوسفند

1392 / 12 / 2

Posted by omidp under Fun Stuff
0 نظرات

بعد از اتفاقی که در پست قبلی افتاد که البته این مشکل توسط خود ما رفع شد و اما دوستان در بانک همچنان درگیر هستند ، تصمیم گرفتم چند نکته دیگر هم اینجا ذکر کنم تا خالی از عریضه نباشه .

همانطور که مستحضر هستید بانک سامان چند وقتی است که فریم ورک UI اینترنت بانک را از JSF به ExtJS تغییر داده که در ابتدا مشکلات کاربری داشت برای نمونه اینجا را کلیک کنید جادی .

از آنجاییکه من با بانک سامان بیشتر از بقیه بانک ها کار می کنم از دوستان تقاضا دارم اقدامات مقتضی را مبذول بفرمایید

نرم افزارهای بانکی ایرانی تولید شده برای استفاده دوستان در ایران است و آیا شما از سرعت اینترنت ایران با خبر هستید ؟؟؟؟

بعد از ورود ، صفحه اول ۱.۲ مگ است با ۵۲ request . حداقل جاوااسکریپت ها و css هایی که استفاده کردید را minified کنید خو ، حجم صفحه کم بشه . ولی باز هم جا داره از آپاچی و cache browser تشکر کنم که تا حدی به ما در این مهم کمک کرده است .

ExtJs فریم ورک خوبی است معمولا برای تولید SPA یا Single Page Application در بانک سامان لینک های زیادی وجود داره که بر روی هر کدام کلیک می کنید حداقل ۵۰ K فایل لود می کند . (‌با کمی اغراق البته )

از همه موارد بالا که بگذریم سخن دوست نکوست

نکته دیگر که شاید چندان هم مهم نباشد ، اگر امکان داره session timeout صفحه را بیشتر کنید .

با احترام

سیتم پرداخت شاپرک یا خرمگس ، پاسارگاد یا پاسارگاو

1392 / 11 / 28

Posted by omidp under Online Biz
2 نظرات

I never admire another's fortune so much that I became dissatisfied with my own.

من با اینکه بعضیا تو ایران بخاطر روابط و قدرتی که دارن بخوان زیادی پول در بیارن مشکلی ندارم ( می تونن ، می کنن ) اما از دوستان تقاضا دارم کسب و کار بقیه رو کساد نکنند . با احتساب امروز الان دو هفته میشه که با جاوا می خواهیم به سیستم پرداخت پاسارگاد وصل شیم اما متاسفانه حتی خودشون هم بلد نیستن این کار و بکنن که هیچ ، حتی پشتیبانی پاسارگاد زحمت نمیده به خودش که از اونجایی که این مجوز رو خریدن یه سوال بپرسه . یه ضرب المثل قدیمی هست که میگه تو که نمی تونی یونجه بخوری ادعای خریت نکن . شما که فقط دات نت بلدید راه انداختن سیستم الکترونیکی بانکیتون چیه .

جالبتر اینجاست که با توجه به مراحلی که داخل راهنما ذکر شده ، کد جاوا رو نوشتم اما کد تولید شده با اطلاعات یکسان با کد تولید شده دات نت فرق می کنه . الان یک روز میشه که کد جاوا رو براشون فرستادم اما هیچ جوابی نیومده بلکه احتمال میدونم عمرا طرف نتوسته کد رو اجرا کنه . بهشم گفتم مشکل داشتی بپرس .

با این سیستم های شخمی که بانک های ما دارن فقط با دات نت و php میشه بهشون درست وصل شد اونم با نمونه کدهایی که خودشون خریدن .

Java Captcha With Spring

1392 / 11 / 18

Posted by omidp under Java
0 نظرات

Captcha with java

اگر شما هم نرم افزار های تحت وب تولید می کنید حتما برایتان پیش آمده که بخواهید مطمئن شوید فرمی که ارسال می شود توسط یک نفر پر شده و نه یک ربات ، به همین منظور از Captcha استفاده می کنند . در این پست نحوه استفاده از jCaptcha و اسپرینگ را با هم خواهیم دید . طبق معمول جاوا API های زیادی برای تولید captcha دارد اما jCaptcha ساده ترین و قابل سفارشی ترین است بطوریکه خواهیم دید که چقدر ساده می توان فونت ان هم تغییر داد .

نحوه تولید captcha

درست کردن یک عکس تصادفی توسط API های جاوایی چندان کار سختی نیست و شما کافیست فقط یک سرولت در web.xml تعریف کنید که کد زیر را اجرا کند .

package com.omidbiz;

import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.context.support.SpringBeanAutowiringSupport;

import com.octo.captcha.service.CaptchaServiceException;
import com.octo.captcha.service.image.ImageCaptchaService;

/**
 * @author omidp
 * 
 */
public class ImageCaptchaServlet extends HttpServlet
{

    @Autowired
    ImageCaptchaService imageCaptchaService;

    public void init(ServletConfig config) throws ServletException
    {
        super.init(config);
        SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, config.getServletContext());
    }

    protected void doGet(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException,
            IOException
    {

        byte[] captchaChallengeAsJpeg = null;
        // the output stream to render the captcha image as jpeg into
        ByteArrayOutputStream jpegOutputStream = new ByteArrayOutputStream();
        try
        {
            // get the session id that will identify the generated captcha.
            // the same id must be used to validate the response, the session id
            // is a good candidate!
            String captchaId = httpServletRequest.getSession().getId();
            // call the ImageCaptchaService getChallenge method
            BufferedImage challenge = imageCaptchaService.getImageChallengeForID(captchaId, httpServletRequest.getLocale());

            // a jpeg encoder
            ImageIO.write(challenge, "jpeg", jpegOutputStream);
        }
        catch (IllegalArgumentException e)
        {
            httpServletResponse.sendError(HttpServletResponse.SC_NOT_FOUND);
            return;
        }
        catch (CaptchaServiceException e)
        {
            httpServletResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            return;
        }

        captchaChallengeAsJpeg = jpegOutputStream.toByteArray();

        // flush it in the response
        httpServletResponse.setHeader("Cache-Control", "no-store");
        httpServletResponse.setHeader("Pragma", "no-cache");
        httpServletResponse.setDateHeader("Expires", 0);
        httpServletResponse.setContentType("image/jpeg");
        ServletOutputStream responseOutputStream = httpServletResponse.getOutputStream();
        responseOutputStream.write(captchaChallengeAsJpeg);
        responseOutputStream.flush();
        responseOutputStream.close();
    }

}

 

نکته قشنگی که در این سرولت وجود دارد نحوه inject کردن کامپوننت های اسپرینگ در آن است که همانطور که مشاهده می کنید متد init مسئول اینکار است . سپس یک صفحه وب jsp یا HTML می سازید

اعتبارسنجی کد وارد شده

حال که ساخت captcha به پایان رسید شما نیاز دارید تا مقدار ورودی کاربر را چک کنید . اینکار هم بسیار راحت است با استفاده از اینترفیس ImageCaptchaService که در بالا از آن برای تولید عکس استفاده کردیم می توان مقدار وارد شده را چک کرد با استفاده از متد validateResponseForID که در واقع جواب مورد نظر را با session id چک می کند که آیا مقدار وارد شده توسط کاربر صحیح است یا خیر . خروجی آن یک boolean است .

شما می توانید در فایل captcha.xml تنظیماتی مانند تغییر فونت ، پیش زمینه و ... را انجام دهید این فایل را می توانید در نمونه پروژه که در گیت  وجود دارد مشاهده کنید .

Being Geek - Mind The GAP

1392 / 11 / 4

Posted by omidp under General
0 نظرات

EVERYONE IS REPLACEABLE...

GEEK ON

اولین باری که این جمله را می شنوید زمانی است که شخصی در حال ترک تیم است . در برخی موارد تیم دچار افسردگی می شود چراکه هیچکس نمی خواهد تا این فرد تیم را ترک کند و در بعضی مواقع اگرچه فردی که از تیم می رود تاثیر چندانی در حال و هوای تیم ندارد اما تیم تحت فشار قرار می گیرد تا جای خالی او را پر کند اینجاست که مدیر مجموعه تیم را فرا می خواند و جلسه ای با صحبت های کلیشه ای مثل این فرد به دنبال موقعیت های جدید است و ... تشکیل می شود اما همه می دانند اگر این صحبت های کلیشه ای واقعی بود دیگر نیازی به این جلسات نبود اینجاست که مدیر به شما می گوید هر کسی قابل جایگزین است و البته حق با اوست.

وقتی کسی از تیم می رود شما شروع به یاد گرفتن چیزهای جدید و جالب در مورد بقیه افراد تیم که باقی مانده اند می کنید

فاصله

در این پست می خواهیم در مورد افرادی صحبت کنیم که شما نمی خواهید از تیم بروند چراکه با توانایی های خود ، ارزش هایی به تیم می افزایند . موقعیت های حیاتی وجود دارد که رفتن یک فرد کلیدی ممکن است منجر به نابود شدن تیم یا حتی شرکت شود اما من فکر می کنم که با این طرز فکر شما بقیه افراد تیم را دست کم گرفته اید واقعیت این است که تیم بسیار ارگانیسم پیچیده ای است و شما نباید نگران ترک افراد از تیم باشید چرا ؟ به خواندن ادامه دهید

دانش و توانایی

ترس از این موضوع که فردی که در حال ترک تیم است ، دانشی درمورد محصول دارد که بقیه ندارند یا او تنها کسی است که کل سیستم را می داند و ما هر وقت مشکلی داشته باشیم از او می پرسیم ، بدون او نمی توانیم مشکلات سخت را حل کنیم باعث می شود تا شما بقیه افراد تیم را دست کم بگیرید در حالی که واقعیت این است شما وقتی می خواهید کاری انجام دهید در واقع دانش انجام آن کار را یا دارید یا به هر زحمتی است آن را کسب می کنید و به زودی متوجه می شوید که این دانش به جای اینکه در یک نفر باشد ، در تیم پخش شده است

وقتی این شخص تیم را رها می کند ، تیم یاد خواهد گرفت چگونه موقعیت های غیرمترقبه را کنترل کند و از پس شرایط سخت برآید البته لازم به ذکر نیست که این کار تمرین روزمره نیاز دارد و رمان بر است و وقتی به یک مشکل فنی بر می خورید واقعا دلتان برای او تنگ خواهد شد اما تیم به مرور یاد خواهد گرفت چگونه بدون او هم زنده بماند و چه چیزهایی فراموش شده

قدرت و تاثیر گذاری

در هر تیمی فردی است که از شما در مقابل حاشیه ها حفاظت می کند . موقعیت های ویژه ای در تیم بخاطر او ایجاد می شود . تصمیم هایی به نفع ما گرفته می شود چرا که او بخاطر ما می جنگد . در واقع رهبران یک تیم فرهنگی ایجاد می کنند و از این فرهنگ به نفع تیم استفاده می کنند . وقتی رهبر یک تیم آن تیم را رها می کند سوالی که شما باید از خودتان بپرسید این است چقدر از این فرهنگ از دست رفته یا باقی مانده ؟؟؟

دیدگاه

دوباره می گویم که یک تیم بسیار ارگانیسم پیچیده ای است و دیدگاه شما به عنوان عضوی از این ارگانیسم از جایگاه خودتان است یعنی فقط شما از دید خود این مسئله را بررسی می کنید اما دیدگاه های متفاوتی در مورد رفتن این شخص وجود دارد که بهتر است به آن ها دقت کنید یکنفر ممکن است کاملا کنترل خود را از دست بدهد ، شخص دیگری ممکن است مدت ها منتظر این فضا باشد تا حرکتی انجام دهد و تکانی بخورد و تمام این واکنش های اجتماعی غیر مترقبه که با رفتن این شخص صورت می گیرد هر روز کار شما را تحت تاثیر قرار میدهد اما این خلا ایجاد شده غیر از سردرگمی ، موقعیت هایی هم با خود به ارمغان می آورد و این شما هستید که باید جای خود را در این تغییرات پیدا کنید

آیا همیشه می خواستید یک تیم را رهبری کنید ؟ آیا کسی را در تیم می شناسید که بتواند این کار را انجام دهد ؟

در آخر ، به یاد داشته باشید که رفتن یک فرد کلیدی از تیم افراد آن تیم را می ترساند چراکه آن ها به این فکر نمی کنند که همه قابل جایگزین هستند آن ها با خود فکر می کنند که بقیه چه چیزهایی می دانند که من نمی دانم ؟ من اینجا خوشحال و راحت نیستم چرا بقیه هستند ؟ نفر بعدی که از تیم جدا خواهد شد کیست ؟

اما بزرگترین ریسک با رفتن یک فرد کلیدی این است که ....................

Atmosphere For Websocket

1392 / 8 / 27

Posted by omidp under Tech Stuff
0 نظرات

وقتی در حال تولید single page application هستید یکی از دغدغه های شما ارسال تغییرات و داده‌ها به کلاینت است بدون آنکه صفحه را refresh کنید در‌واقع این سرور است که بدون آنکه کلاینت درخواست دهد، باید تغییرات را به کلاینت بفرستد اصطلاحاً به این کار کامت یا پوش می‌گویند . اما چگونه باید اینکار را انجام داد ؟ جواب این سؤال خیلی هم ساده نیست . چراکه پیدا کردن فریم ورکی که هم websocket و هم long-polling پشتیبانی کنید آن هم بر روی تمام مرورگرها حتی اندورید و بتوان آن را در تمام وب سرورهای جاوا deploy کرد ، مفاهیم کوئری پارامتر هم در سوکت داشته باشد و مهمتر از بقیه با spring security هم بتوان یکپارچه کرد تقریباً غیر ممکن است .

تا جاییکه من می‌دانم جاوا چند روش برای انجام این کار دارد

  • cometD : که یکی از پروژه های dojo foundation است
  • jWebSocket
  • Atmosphere

 

در این پست به اتمسفر می‌پردازیم چراکه تمام مطالبی که بالا گفته شد بعلاوه یکپارچگی با خیلی تکنولوژی های دیگر مثل redis و jersey هم دارد .

طراحی این فریم ورک بی‌نظیر است بطوریکه خیلی از شرکت های بزرگ مثل primefaces ، Vmware و … در production از آن استفاده می‌کنند ابتدا اجازه دهید برخی مفاهیم را مرور کنیم .

قسمت کلاینت

Subscribe : کانالی است که کلاینت بر روی آن منتظر گرفتن تغییرات می‌شود

Push : پیامی که کلاینت به سرور می‌فرستد شما می‌توانید از این پیام برای آنالیز درخواست کلاینت مانند sorting و paging استفاده کنید .

$(function () {
   var request = {
     url: document.location.toString() + 'echo' + Math.random().toString(),
     transport : "websocket" ,
     fallbackTransport: 'long-polling'};

   request.onMessage = function (response) {
     console.log(response.responseBody)
   };
   $.atmosphere.subscribe(request).push({paging : '0-20'});
}

 

سمت سرور

@AtmosphereHandlerService(path = "/echo/{id}", supportSession = true, broadcasterCache = UUIDBroadcasterCache.class, broadcaster = SimpleBroadcaster.class, interceptors = {
        AtmosphereResourceLifecycleInterceptor.class, BroadcastOnPostAtmosphereInterceptor.class, HeartbeatInterceptor.class})
public class Echo extends OnMessage {
    @Override
    public void onMessage(AtmosphereResponse res, String m) {
        res.write("Echo: " + m);
    }
}

 

زمانیکه کلاینت subscribe می‌کند کانکنشن باید suspend شود . زمانیکه کلاینت push می‌کند شما اطلاعات خواسته شده را broadcast می‌کنید .

Broadcast

مهمترین مفهوم در اتمسفر است . در‌واقع این broadcaster ها هستند که کلاینت را خبر می‌کنند نکته جالب در اتمسفر این است که شما می‌توانید رو هوا broadcaster جدید بسازید و آن را به resource خود اضافه کنید اینکار به شما کمک می‌کند تا بجای اینکه کلاینت بر روی چند کانال subscribe کند شما اطلاعات را بر روی یک کانال با چند broadcaste مختلف ارسال کنید .

https://github.com/Atmosphere/atmosphere/wiki/Understanding-Broadcaster

 

MetaBroadcaster.getDefault().broadcastTo("/*/echo/{username}", "hello world");

 

اتمسفر به شدت انعطاف پذیر است به عنوان مثال اگر می‌خواهید با spring security آن را یکپارچه کنید می‌توانید یک interceptor برای اینکار بنویسید .

پست های بعدی

  • نوشتن SDK با جاوا
  • Command Design Pattern
  • Openbravo POS in Iran
  • Maven & Postgresql Cheat sheet
  • Titanium Platform for Android Mobile Development

 

Effective Team

1392 / 6 / 27

Posted by omidp under General
0 نظرات

در هر شرکتی برای ساخت نرم افزار جلسات مختلفی بین افراد شکل می گیرد

مالک نرم افزار : من قابلیت X را لازم دارم

مدیر فنی : منظور از قابلیت X یعنی ...

توسعه دهندگان : کدام یک را می خواهی قربانی کنی زمان کیفیت یا قابلیت

صحبت های بیشتر ، ترجمه های بیشتر و توهم اینکه کار در حال پیشرفت است اما در واقع شما فقط در حال صحبت کردن هستید و هیچ چیزی نمی سازید و لازم است تا کسانی تصمیم گیری کنند

Damned Triangle

زمان ، قابلیت و کیفیت در واقع مثلثی است که وضعیت محصول شما را تعیین می کند در دنیای ایده آل این سه در تعادل هستند تعادل بین زمانی که شما نرم افزار را release می کنید ، کیفیتی که به دنبالش هستید و قابلیتی که می خواهید پیاده کنید

در دنیای واقعی این سه هیچ وقت در تعادل نیستند یعنی در واقع این ها مدل ذهنی هستند که به شما این امکان را می دهند تا دروغ هایتان را توجیه کنید به بحث زیر توجه کنید

مالک نرم افزار : این قابلیت باید world class باشد

توسعه دهندگان : ما 4 هفته بیشتر زمان لازم داریم چراکه هم درخواست دیر داده شده هم این یک قابلیت جدید است

مالک نرم افزار : این زمان خیلی دیر است من تعهد دارم

توسعه دهنده گان : کار بیشتری اضافه شده پس انتخاب کن زمان بیشتر یا کیفیت کمتر

به کرات این بحث های سیاه و سفید را شنیده ایم به عقیده من سه اهرم مشخص کننده این است که یک محصول آیا ارزش دارد یا خیر

اهرم اول

کسی که وقتی یکی از اعضای تیم سوال دارد از او می پرسد . کسی که می تواند با یک کلام یک بحث چند ساعتی را تمام کند

اهرم دوم

کسی که محتوای محصول را تعیین می کند و می داند که محصول باید چگونه باشد با خونسردی می تواند توضیح دهد که چرا این قابلیت برای محصول لازم است

اهرم سوم

تعیین و شناخت این اهرم سخت است چراکه در هر کجای تیم می تواند قرار گیرد . اطلاعات زیادی روزانه در تیم های مختلف جا به جا می شود تصمیمات زیادی گرفته می شود . این اهرم تمام اطلاعات را جمع می کند و تحلیل می کند . این شخصی است که وقتی شما از خودتان می پرسید اینجا چه خبر است او دقیقا می داند دلیل واقعی اینکه چرا هنوز محصول تولید نشده چیست

Effective Team

اگر شما این سه رهبر را ندارید و در تیمی بیش از یک نفر کار می کنید هیچ وقت قادر نخواهید بود چیزی تولید کنید

سه رهبر که برای پیاده سازی یک قابلیت می توانند تصمیم گیری کنند دانش و مهارتی دارند که محصول انجام کار است و اگر شما مشکلی داشته باشید آن ها با یک راه حل ساده به کمکتان می آیند من اعتقاد دارم که این سه عنصر شاید لازمه یک کسب و کار بهره ور و موثر نباشد اما لازمه یک تیم موثر است

مالک نرم افزار تصور می کند که تیم توسعه هیچ وقت به زمان بندی نمی رسد حتی اگر برای آن ها جریمه و پاداش تعیین کند تیم توسعه هم فکر می کند که هر کسی که نمی تواند کد بزند بی مصرف است و محصول بدون آن ها هیچ است

این تصور آزار دهده است به جز زمانی که نوبت این سه اهرم می رسد. قدرت تصمیم گیری این افراد یک تنش سالم در تیم ایجاد می کند

همه افراد در تیم بر این عقیده هستند که کارشان از همه مهمتر است و در غیاب آن ها کار از هم می پاشد . این یک عقیده است که ما برای خود نگه می داریم و این عقیده به ما اعتماد به نفس می دهد تا تصمیم گیری کنیم با همه افراد تیم بحث کنیم تا حرف خود را به کرسی بنشانیم من از همه بهترم پس حق با من است

اما نکته اینجاست که در مقابل این سه اهرم ما به خود می گوییم او از من بهتر می داند و احترام و اعتمادی برای این سه اهرم قائل هستیم و اینطوری شما می توانید نرم فزار تولید کنید نه با روش مزخرف Agile که شما دو برابر زمانی که نرم افزار تولید می کنید باید صرف کنید تا افراد بی تجربه را قانع کنید

مهارت های این سه اهرم متفاوت است کسی که هفت سال سابقه کد زنی دارد کاملا دیدگاه متفاتی دارد با کسی که می داند یک قابلیت چگونه مورد پسند کاربر قرار می گیرد چیزی که چندین سال کد زنی هم به شما نمی تواند بدهد

Let the negotiation begin

در واقع من سه عنصر زمان ، کیفیت و قابلیت را با این سه اهرم جایگزین کردم. راه های زیادی برای خراب کردن این مدل با افراد بی تجربه وجود دارد اما من اعتقاد دارم نه تنها این مدل بطور واقع بینانه ای افراد تیم را هول می دهد بلکه محصول شما را در مسیر متفاوتی قرار می دهد

نرم افزار ساخته ی دست افراد است . افرادی که عنوان دارند و این عنوان ها را نه فقط بخاطر تصمیمات خوب خود در حیطه تخصصشان بدست آورده اند بلکه بخاطر اینکه می دانند چه موقع از چه کسی کمک بخواهند . بدون آن ها هیچی ساخته نخواهد شد

Let's build software together

1392 / 6 / 5

Posted by omidp under General
0 نظرات

متن باز همیشه یکی از بحث‌های مورد علاقه من بوده و هست چراکه اولین کار حرفه‌ای خودم را بر روی یک نرم‌افزار متن باز بنام ادمپیر شروع کردم . بعلاوه خیلی از سازمان ها نرم افزارهای خود را بر روی این بسترها می‌سازند و از این طریق کسب درآمد می کنند بدون آنکه کوچکترین کمکی به این اکوسیستم کنند به عنوان عضو کوچکی از این جامعه همیشه دوست داشتم تا دین خودم را به نحوی ادا کنم اگرچه هیچ وقت موفق نشدم اما با افراد زیادی در این راه آشنا شده و چیزهایی زیادی یاد گرفتم .

اگر که می‌خواهید برنامه نویس خوبی شوید ، پیشنهاد می‌کنم حتماً در یک پروژه متن باز شرکت کنید . حتی اگر دنبال کار هستید باز هم اینکار را انجام دهید به ضرس قاطع می‌گویم که شرکت در یک پروژه متن باز ثمره بیشتری برای شما خواهد داشت تا شرکت در کلاس‌های آموزشی ای که به شما وعده استخدام در شرکت های مختلف را می‌دهد یا شرکت در آزمون هایی که فقط برای پول درآوردن طراحی شده است .

مسأله دیگری که همچنان برای من گنگ است این است که چرا برخی از شرکت های نرم افزاری به نظر صاحبش معتبر که کارشان هم فقط دانلود و چسباندن چند تا فریم ورک جاوا به یکدیگر و استفاده از آن ها ست برخی از محصولاتشان را متن باز نمی‌کنند با وجود اینکه مزیت اینکار بیشتر از معایبش است هر چه باشد در ایران موتور جستجوی گوگل که تولید نمی‌شود که به خواهیم سورس آن را از همه مخفی کنیم اینکاری که شما ، شرکت محترم ، انجام می‌دهید خیلی‌های دیگر می‌توانند انجام دهند در زیر به برخی از مزایای اینکار اشاره شده است :

اگر در حال استخدام هستید بهترین نوع مصاحبه است به هر حال اشخاصی که به پروژه شما ابراز علاقه‌مندی می‌کنند و بر روی آن کار می‌کنند برای شما مناسب‌تر هستند

آدم‌های باهوش دوست دارند در کنار بقیه افراد باهوش باشند پس وقتی که شما پروژه ای ارزشمند را متن باز می‌کنید خیلی از استعدادهای خوب را مجانی جذب می‌کنید .

چه چیزهایی را باید متن باز کنید ؟

تقریباً هر چیزی که کسب و کار شما را در بر ندارد . مثلاً اگر بر روی یک پروژه بانکی کار می‌کنید و یک ماکروفریم ورک با اسپرینگ تولید کردید که عملیات CRUD را برای شما آسان می‌کند می‌توانید آن را متن باز کنید .

در سایت امیدبیز یک lab باز شده که پروژه های متن بازی که تاکنون بر روی آن‌ها کار کرده‌ام و از آن‌ها استفاده می‌کنم بصورت متن باز در اختیار همه قرار گرفته . لازم به ذکر است که این پروژه ها روز به روز در حال بیشتر شدن است و خوشحال میشم اگر کسی مشارکت کند .

منبع :

 
http://tom.preston-werner.com/2011/11/22/open-source-everything.html

نکته دیگر که در همین جا مطرح می‌کنم برای کاربران می ون که با تحریم ها و دانلود برخی کتابخانه‌ های جاوا مشکل دارند یک مخزن nexus در همین سایت راه اندازی شده که با استفاده از آن می‌توانند مشکل خود را حل کنند .

 
 <repository>
     <id>omidbiz_repo</id>
     <url>http://nexus.omidbiz.com/content/sites/omidbiz_repo</url>
 </repository>

Main | Next page »