<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های محمد سپهر ملائی</title>
        <link>https://virgool.io/feed/@sepehrmsm1379</link>
        <description>توسعه‌دهنده بک‌اند جاوا</description>
        <language>fa</language>
        <pubDate>2026-06-16 14:01:09</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/265391/avatar/b1UPhA.jpg?height=120&amp;width=120</url>
            <title>محمد سپهر ملائی</title>
            <link>https://virgool.io/@sepehrmsm1379</link>
        </image>

                    <item>
                <title>مقدمه ای بر کَمِل</title>
                <link>https://virgool.io/javacup/%D9%85%D9%82%D8%AF%D9%85%D9%87-%D8%A7%DB%8C-%D8%A8%D8%B1-%DA%A9%D9%8E%D9%85%D9%90%D9%84-baextthcahsp</link>
                <description>در قسمت قبل الگوهای ادغام سازمانی (Enterprise Integration Patterns) را به صورت مختصر معرفی کردیم. در ادامه با یکی از ابزارهایی که برای پیاده سازی این الگوها استفاده می شود، آشنا می شویم.کمل (Apache Camel)، یکی از چهارچوب هایی است که امکان ادغام سرویس های تولید کننده و مصرف کننده را فراهم می کند. این پروژه در اوایل سال 2007 آغاز شده و در حال حاضر به صورت منبع باز و تحت مجوز Apache 2.0 در دسترس قرار گرفته است. جهت بررسی بیشتر، پیشنهاد می کنیم به Camel in Action, Second Edition مراجعه کنید.مقدمهبه صورت کلی کمل این امکان را برای شما فراهم می کند که برای سیستم پیامگرای خود، قواعد مسیریابی تعریف کنید. این قواعد را می توان به صورت زیر بیان کرد اینکه پیام ها:از کدام منبع دریافت شوندبه چه صورت پردازش شوندبه کدام مقصد هدایت شوند همانطور که قبلا هم اشاره کردیم، از چالش های مهم ادغام سرویس ها، پیاده سازی مختلف آن ها است. هر سرویس انتظار دارد که نوع داده خاصی را در پیام ها استخراج کند. همچنین ممکن است از پروتکل های مختلفی پیشتیبانی بکند. کمل با ارائه واسط های مختلف و پیاده سازی حالت های بسیار از آن ها، تا حد ممکن این مشکلات را از توسعه دهنده پنهان می کند. برخی از مهمترین امکاناتی که کمل در اختیار ما قرار می دهد عبارتند از:1. واسط مسیریابیهسته اصلی کمل که امکان انتقال پیام ها را میان اجزاء مختلف با توجه به مسیر های ایجاد شده به وسیله توسعه دهنده فراهم می کند. این مسیرها به وسیله الگوهای ادغام سازمانی (EIP) و زبان واسط (DSL) تنظیم می شوند که در ادامه شرح خواهیم داد.2. کامپوننت های گستردهدر کمل، کتاب خانه گسترده ای از کامپوننت های مختلف ارائه شده که هر کدام برای بهره وری از واسط ها و تبدیل داده استفاده می شوند. کامپوننت ها امکان تعامل با سایر نرم افزار ها را فراهم می کنند.3. مطابق با الگوهای ادغام سازمانیبا وجود اینکه الگوهای ادغام سازمانی EIP مشکلات ادغام و راه حل آنها را توصیف می کند؛ اما آن ها را به صورت رسمی پیاده سازی نمی کند. کمل با ارائه زبانی خاص و مشترک میان همه توسعه دهندگان تلاش کرده تا حد ممکن این شکاف را برطرف کند.4. زبان واسط domain-specific language (DSL)کمل با ارائه زبان واسط تلاش می کند یکپارچگی خاصی در زمینه پیاده سازی الگوهای ادغام سازمانی ارائه بدهد و توسعه دهنده به جای تمرکز بر پیاده سازی این الگوها، بر ارائه راه حل تمرکز کند. این زبان واسط به شکل کد جاوا یا فرمت XML قابل استفاده است:Java DSLXML DSL به منظور سادگی در ادامه از Java DSL استفاده خواهیم کرد. برای شروع پیشنهاد می کنیم مثال کپی کردن فایل از مبدا به مقصدی خاص را از گیتهاب بررسی کنید. معماری کملدر ادامه هر یک از اجزاء معماری کمل را به صورت مختصر بررسی می کنیمCamel ArchitectureCamel contextهمه اجزا را کنار هم قرار داده و امکان اجرای کمل را فراهم می کند. هر مسیر(Route)ی که به وسیله توسعه دهنده تنظیم می شود، به وسیله Camel context نگهداری شده و به بهره برداری می رسد.Routing engineهمان چیزی که پیام ها را میان اجزاء تولید کننده و مصرف کننده انتقال می دهد. Routing engine استفاده ای برای توسعه دهنده ندارد؛ اما خوب است بدانیم که انتقال پیام ها به وسیله آن انجام می شود.Routesمسیرها به وسیله توسعه دهنده تعریف می شوند. یک مسیر ساده می تواند زنجیره ای از پردازش ها را میان مبدا و مقصد داشته باشد که به وسیله Processor ها انجام می شود. در کمل هر مسیر فقط یک مبدا خواهد داشت که تولید کننده و مصرف کنندگان را از یکدیگر مستقل می کند؛ بنابراین حتی اگر به شکل زیر چندین مبدا برای یک مسیر در نظر بگیریم: from(&#039;jms:queue:A&#039;, &#039;jms:queue:B&#039;, &#039;jms:queue:C&#039;).to(&#039;jms:queue:D&#039;);در نهایت کمل آن را به شکل زیر برداشت خواهد کرد:from(&#039;jms:queue:A&#039;).to(&#039;jms:queue:D&#039;); 
from(&#039;jms:queue:B&#039;).to(&#039;jms:queue:D&#039;); 
from(&#039;jms:queue:C&#039;).to(&#039;jms:queue:D&#039;);Processorsاز مهمترین اجزاء کمل که امکان دسترسی به پیام ها و مدیریت آن ها را فراهم می کند. Processor ها می توانند همزمان به صورت تولید کننده و مصرف کننده عمل کنند؛ به گونه ای که هر Processor پیام های پردازش شده به وسیله Processor قبلی خودش را دریافت کند. مثال قسمت قبل را در نظر بگیرید که بخواهیم پیام های دریافت شده از طرف کاربر را ابتدا رمزگشایی کرده و پس از انجام عملیات احراز هویت پیام های اسپم را نادیده بگیریم. این ویژگی به شکل زیر به وسیله Java DSL قابل پیاده سازی می باشد: from(&#039;direct:start&#039;)
.process(decryptionProcessor)
.process(authenticationProcessor)
.process(spamTrashProcessor)
.to(&#039;direct:end&#039;);نحوه پیاده سازی Processor ها در ادامه بررسی خواهیم کرد.Componentsکامپوننت ها امکان تعامل با سایر واسط ها را با وجود پروتکل های گوناگون و فرمت داده متفاوت فراهم می کنند. با استفاده از آن ها می توانید پیام های موجود در یک کارگزار پیام (Message broker) را استخراج کنید یا به یک دیتابیس خاص کوئری بزنید یا حتی رویداد های یک ربات تلگرام را پردازش کرده و نتیجه را برگردانید. به طور خاص کامپوننت ها به وسیله نام خود در URI مورد استفاده قرار می گیرند. به عنوان مثال فرض کنید می خواهیم به فایلی در مسیر خاص دسترسی پیدا کنیم:from(&#039;file:data/inbox&#039;)در این حالت اسم file، در حقیقت FileComponent را مشخص می کند که امکان دسترسی به مسیر data/inbox را فراهم می کند. در کمل کامپوننت های متنوعی تعریف شده اما امکان توسعه کامپوننت جدید هم وجود دارد. کامپوننت ها به عنوان کارخانه ای از Endpoint ها عمل می کنند.Endpointsبه عنوان واسطی میان اجزا و سیستم پیامگرا مورد استفاده قرار می گیرند. تولید کننده و مصرف کننده به وسیله Endpoint، پیام ها را دریافت کرده یا ارسال می کنند. در کمل، پیام ها در حقیقت به صورت یک Exchange میان اجزاء رد و بدل می شوند که به وسیله Endpoint ها مدیریت می شوند. در تصویر فوق فیلد های یک Exchange را مشاهده می کنید. یکی از مهمترین آنها MEP است. یک الگوی تبادل پیام (Message Exchange Pattern) یا به اختصار MEP، نوع پیامگرایی را به صورت یک طرفه یا درخواست پاسخ مشخص می کند. MEP موجود در یک Exchange، مقادیر زیر را میتواند داشته باشد:1. InOnly پیام گرایی یک طرفه. ساده ترین مثال آن می تواند استفاده از یک کارگزار پیام باشد.2. InOutمدل درخواست پاسخ که به عنوان مثال می تواند در HTTP مورد استفاده قرار بگیرد.در مثال فوق می بینید که Exchange هایی که فیلد MEP برابر با InOut دارند، به مصرف کننده بازگردانده می شوند.Routingدر این قسمت نوشتن مسیر در کمل را بررسی خواهیم کرد و بخشی از الگوهای EIP را به وسیله آن پیاده سازی می کنیم.امروزه مسیریابی را می توان در بسیاری از روزمرگی های خودمان مشاهده کنیم. به عنوان مثال، وقتی نامه ای را پست می کنید؛ ممکن است قبل از رسیدن به آدرس نهایی، از چندین شهر عبور کند. ایمیلی که ارسال می کنید؛ قبل از رسیدن به مقصد نهایی از طریق بسیاری از سیستم های شبکه کامپیوتری هدایت می شود. در همه موارد، مسیریاب انتخاب می کند که بسته دریافتی را از چه راهی به مقصد بفرستد.در سیستم های نرم افزاری پیامگرا، مسیریابی فرایندی است که طی آن پیام از یک مبدا دریافت شده و پس از پردازش، با توجه به مجموعه ای از شروط، به مقصد مناسب هدایت می شود. کمل با بهره گیری از الگوهای تعریف شده معماری پیامگرا، امکان توسعه سیستم های مبتنی بر این رویکرد را فراهم می کند. در ادامه مثال هایی از پیاده سازی موارد ساده به وسیله Java DSL را بررسی خواهیم کرد.استفاده از تایمربه عنوان اولین مثال، نشان می دهیم که چگونه پیام خاصی را طی یک بازه زمانی مشخص در خروجی چاپ کنیم.برای تعریف مسیر به وسیله Java DSL لازم است که از کلاس RouteBuilder ارث بری کنیم. این کلاس متد configure را در اختیار ما قرار می دهد که در آن پیاده سازی خودمان را انجام می دهیم:public class MyRouteBuilder extends RouteBuilder {
    @Override
    public void configure() throws Exception {
        from(&#039;timer:foo?period=5000&#039;)
            .transform(simple(&amp;quotHello&amp;quot))
            .log(&#039;${body}&#039;);
    }
}کامپوننت Timer برای ایجاد پیام در یک بازه زمانی مشخص استفاده می شود. این پیام ها به صورت یک رویداد (event) تولید می شوند. در این مثال اسم کامپوننت را foo در نظر گرفته ایم و مقدار بازه زمانی دلخواه را برابر 5 ثانیه قرار داده ایم. در ادامه به وسیله متد transform، پیام Hello را در بدنه ورودی (Body) قرار داده و سپس آن را چاپ می کنیم.همانطور که قبلا هم گفتیم، در کمل تمام مسیرهای تعریف شده به وسیله CamelContext نگهداری می شوند و به بهره برداری می رسند. لذا در متد Main:public final class MyCamelApplication {
    public static void main(String[] args) throws Exception {
        CamelContext context = new DefaultCamelContext();
        context.addRoutes(new MyRouteBuilder());
        context.start();
    }
}توجه داشته باشید که در مثال فوق کمل فرصتی برای چاپ پیام Hello نخواهد داشت زیرا ترد اصلی که به وسیله main ایجاد شده به انتها می رسد. برای حل این مشکل متد main دیگری ایجاد می کنیم:import org.apache.camel.main.Main;

public class MyApplication {
    public static void main(String[] args) throws Exception {
        Main main = new Main(MyCamelApplication.class);
        main.run();
    }
}که به خروجی زیر منجر می شود:استفاده از Processor هاکامپوننت Timer برای هر پیامی که ارسال می کند یک هدر HEADER_FIRED_TIME تنظیم می کند که زمان تولید آن پیام را به شکل روز هفته، ماه، ساعت و سال میلادی نشان می دهد. در این قسمت قصد داریم هدری به هر پیام اضافه کنیم؛ به طوری که روز هفته شمسی (شنبه، یکشنبه و ...) را بیان کند. این کار را به کمک یک پردازه (Processor) انجام می دهیم.ابتدا یک Enum برای مدل کردن روزهای هفته در نظر میگیریم:public enum WeekDays {
    
    Sat(&#039;شنبه&#039;),
    Sun(&#039;یکشنبه&#039;),
    Mon(&#039;دوشنبه&#039;),
    Tue(&#039;سه شنبه&#039;),
    Wed(&#039;چهارشنبه&#039;),
    Thu(&#039;پنجشنبه&#039;),
    Fri(&#039;جمعه&#039;);

    private final String name;

    WeekDays(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}برای پیاده سازی یک پردازه، لازم است که از واسط org.apache.camel.Processor استفاده کنیم. این واسط متدی به نام process فراهم می کند که امکان دسترسی به Exchange دریافتی را می دهد:public class TimerProcessor implements Processor {
    @Override
    public void process(Exchange exchange) throws Exception {
        final Message message = exchange.getMessage();
        final String firedTime = message.getHeader(
                TimerConstants.HEADER_FIRED_TIME, String.class
        );

        WeekDays weekDay = Arrays.stream(WeekDays.values())
                        .filter(weekDays -&gt; firedTime.contains(weekDays.toString()))
                        .findFirst().get();

        exchange.getMessage().setHeader(&#039;dayOfWeek&#039;, weekDay.getName());
    }
}در مثال فوق ابتدا پیام را از Exchange دریافتی استخراج کرده سپس با توجه به محتوای هدر پیام، مشخص می کنیم که کدام یک از روزهای هفته را باید در نظر بگیریم. در پایان نتیجه را به عنوان هدر جدیدی به نام dayOfWeek در پیام قرار می دهیم.برای استفاده از TimerProcessor لازم است که آن را به Java DSL قبلی اضافه کنیم:public class MyRouteBuilder extends RouteBuilder {

    @Override
    public void configure() throws Exception {
        from(&#039;timer:foo?period=5000&#039;)
            .transform(simple(&#039;Hello&#039;))
            .process(new TimerProcessor())
            .log(&#039;${body} on ${header.dayOfWeek}&#039;);
    }
}مشاهده می کنید که کمل امکان دسترسی به هدر و بدنه را در متد log فراهم می کند که منجر به خروجی زیر خواهد شد:استفاده از Message Routerدر قسمت الگوهای پیامگرایی دیدیم که مسیریاب پیام، فیلتری است که می تواند با استفاده از هدر های یک پیام، آن را به خروجی مناسب هدایت کند. در این بخش مثال قبل را توسعه می دهیم به گونه ای که پیام هایی که در روز زوج ساخته شده باشند به یک صف خاص، و روزهای فرد برای صف دیگر هدایت شود.public class MyRouteBuilder extends RouteBuilder {

    private static final String DAY_OF_WEEK = &#039;dayOfWeek&#039;
    private static final String EVEN_QUEUE = &#039;direct:even&#039;
    private static final String ODD_QUEUE = &#039;direct:odd&#039;
    private static final String ANOTHER_QUEUE = &#039;direct:another&#039;


    @Override
    public void configure() throws Exception {
        from(&#039;timer:foo?period=5000&#039;)
            .transform(simple(&#039;Hello&#039;))
            .process(new TimerProcessor())
            .choice()
                .when(exchange -&gt; {
                    final String day = exchange.getMessage().getHeader(DAY_OF_WEEK, String.class);
                    return day.contains(WeekDays.Sat.getName()) ||
                           day.contains(WeekDays.Mon.getName()) ||
                           day.contains(WeekDays.Wed.getName());
                }).to(EVEN_QUEUE)
                .when(exchange -&gt; {
                    final String day = exchange.getMessage().getHeader(DAY_OF_WEEK, String.class);
                    return day.contains(WeekDays.Sun.getName()) ||
                            day.contains(WeekDays.Tue.getName()) ||
                            day.contains(WeekDays.Thu.getName());
                }).to(ODD_QUEUE)
                .otherwise().to(ANOTHER_QUEUE)
            .end()
            .log(&#039;${body} on ${header.&#039; + DAY_OF_WEEK + &#039;}&#039;);
        
            // We have to process all queues in our messaging system
           from(EVEN_QUEUE).process();
           from(ODD_QUEUE).log(&#039;I\&#039;ll be processed before logging body and header&#039;).process();
           from(ANOTHER_QUEUE).process();
    }
}مشاهده می کنید که پیام ها با توجه به مقدار هدر DAY_OF_WEEK، به یکی از کامپوننت های direct:even، direct:odd یا direct:another هدایت می شوند. کامپوننت direct، امکان فراخوانی سنکرون برای پردازش پیام ها را فراهم می کند؛ به عبارت دیگر تا زمانی که پیام به وسیله زیر مجموعه های آن direct پردازش نشود؛ سراغ کامپوننت های دیگر نخواهد رفت. در ادامه پیام های دریافتی از هر یک از صف ها را به طور نمونه پردازش خواهیم کرد که منجر به خروجی زیر خواهد شد: direct componentبرخلاف direct، کامپوننت SEDA امکان فراخوانی آسنکرون را فراهم می کند؛ لذا با تغییر نام direct به seda خروجی به شکل زیر غیر قابل پیش بینی خواهد بود:seda componentاستفاده از Message brokerدر ادامه پیام های تولید شده به وسیله تایمر را به یک کارگزار پیام ارسال می کنیم. در این مثال ما از ActiveMQ استفاده می کنیم؛ بنابراین وابستگی مربوط کامپوننت آن را به پروژه خود اضافه می کنیم:&lt;dependency&gt;
  &lt;groupId&gt;org.apache.camel&lt;/groupId&gt;
  &lt;artifactId&gt;camel-activemq&lt;/artifactId&gt;
&lt;/dependency&gt;همچنین برای اتصال به ActiveMQ:&lt;dependency&gt;  
    &lt;groupId&gt;org.apache.activemq&lt;/groupId&gt;  
    &lt;artifactId&gt;activemq-all&lt;/artifactId&gt;  
    &lt;version&gt;5.15.2&lt;/version&gt; 
&lt;/dependency&gt; 
حال ابتدا کامپوننت مورد نیاز را به Camel context اضافه می کنیم:var connectionFactory = new ActiveMQConnectionFactory(&#039;vm://localhost&#039;);
var context = new DefaultCamelContext(); 
context.addComponent(
    &#039;amq&#039;,    
    JmsComponent.jmsComponentAutoAcknowledge(connectionFactory)
); 
در اینجا برای اتصال به ActiveMQ از شی connectionFactory استفاده کرده ایم. ورودی vm://localhost امکان استفاده از یک Embedded broker را فراهم می کند. درنهایت پیام ها را به صف sample ارسال می کنیم:from(&#039;timer:foo?period=1000&#039;)
.transform(simple(&#039;Hello&#039;))
.to(&#039;amq:queue:sample&#039;);پیوند های مفیدایجاد پروژه اولیه کمل با توجه به وابستگی های مشخص شده: Kameleonلیستی کامل از کامپوننت های کمل: Componentsمثال هایی از پیاده سازی الگوهای سازمانی با استفاده از کمل: Camel-Enterprise-Integration-Patterns</description>
                <category>محمد سپهر ملائی</category>
                <author>محمد سپهر ملائی</author>
                <pubDate>Fri, 26 Aug 2022 11:26:32 +0430</pubDate>
            </item>
                    <item>
                <title>مقدمه ای بر الگوهای ادغام سازمانی</title>
                <link>https://virgool.io/javacup/%D9%85%D9%82%D8%AF%D9%85%D9%87-%D8%A7%DB%8C-%D8%A8%D8%B1-%D8%A7%D9%84%DA%AF%D9%88%D9%87%D8%A7%DB%8C-%D8%A7%D8%AF%D8%BA%D8%A7%D9%85-%D8%B3%D8%A7%D8%B2%D9%85%D8%A7%D9%86%DB%8C-ljct3rwtqyxu</link>
                <description>پیامگرایی (Messaging) از جمله رویکردهایی هست که برای ارتباط بین میکروسرویس ها استفاده می شود و همچنین الگوهای ادغام سازمانی (Enterprise Integration Patterns) به اختصار EIP، به الگوهای طراحی اشاره می کنند که برای ادغام نرم افزار هایی استفاده می شود که از رویکرد Messaging استفاده می کنند.کتاب الگوهای ادغام سازمانی به طور ویژه رویکرد Messaging را بررسی میکنداصطلاح EIP دقیقا برگرفته از کتابی با همین نام است که اولین بار در سال 2003 منتشر شد. در این کتاب راهکارها و استاندارد های مختلفی برای طراحی سیستم های پیامگرا پیشنهاد می شود و سپس یک پیاده سازی ابتدایی برای آن ها ارائه می شود. در ادامه برخی از این الگوها و استاندارد ها را معرفی می کنیم.جهت بررسی بیشتر می توانید به enterpriseintegrationpatterns.com مراجعه کنید.مقدمهفارغ از مزایایی که میکروسرویس ها می توانند برای ما داشته باشند، ادغام آنها چالش های زیادی برای ما دارد که برخی از مهمترین آنها عبارتند از:هر نرم افزاری پیاده سازی مخصوص به خودش را دارد: ادغام سرویس ها به دلیل نوع پیاده سازی مختلف آنها (زبان برنامه نویسی، معماری و ...) چالش های مخصوص به خودش را خواهد داشت. یک الگوی ادغام نرم افزار، باید واسط مناسبی برای از بین بردن تفاوت بین نرم افزار ها ارائه کند.تغییر در نرم افزار اجتناب ناپذیر است: نرم افزار به طور مداوم درحال تغییر است. اگر یکی از سرویس ها به هر دلیلی تغییر کند می تواند سایر بخش ها را تحت تاثیر قرار دهد. یک الگوی ادغام باید تا حد ممکن وابستگی میان سرویس ها را کاهش دهد.توسعه دهندگان برای غلبه بر این چالش ها از روش های گوناگونی استفاده کردند این کتاب به صورت اختصاصی رویکرد پیامگرایی را برای ادغام سرویس ها مورد بررسی قرار می دهد.پیامگرایی (Messaging)برای توصیفی دقیق از پیامگرایی اجازه بدهید مثالی خدمتتون ارائه بدهیم. فرض کنید با یک نفر از دوستان خودتان تماس تلفنی برقرار می کنید. در این حالت ارتباط شما از نوع سنکرون می باشد چرا که تا زمانی که با او مکالمه می کنید، نمیتوانید با شخص دیگری تماس بگیرید. حال فرض کنید به هر دلیل امکان تماس با دوستتان را نداشته باشید یا آنقدر مشغول باشید که نتوانید با او مکالمه کنید. در این حالت شما از طریق ایمیل، پیامی برای او ارسال کرده و کار خودتان را از سر میگیرید. دوستتان هر زمان که خواست، ایمیل خود را چک کرده و پیام شما را می خواند این همان چیزی است که به عنوان ارتباط آسنکرون شناخته می شود. پیام گرایی در حقیقت امکان تعامل آسنکرون میان سرویس های شما را فراهم می کند. هر سرویس پیام خود را در کانال قرار داده و کار خودش را ادامه می دهد بدون آنکه منتظر پاسخ گیرنده بماند.اجزاء اصلی در یک معماری پیامگرا عبارتند از:پیام(Message): که میان سرویس ها رد و بدل می شودکانال(Channel): اتصال میان سرویس هارا برقرار کرده و امکان انتقال پیام را فراهم می کنند کانال ها به وسیله سیستم پیامگرا مدیریت می شودتولید کننده(Producer)مصرف کننده(Consumer)قابلیت های پیام گرایی در حقیقت به وسیله واسط جداگانه به نام Messaging system ارائه می شود که با عنوان (message-oriented middleware (MOM هم شناخته می شود. در این واسط، اقدامات مربوط به مدیریت پیام انجام می شود و وظیفه هدایت پیام از تولید کننده به مصرف کننده را دارد. یک سیستم پیامگرا قابلیت ها و اجزاء متفاوتی دارد که خدمت شما شرح خواهیم داد.در حالت کلی برای انتقال داده در یک معماری پیامگرا:آنچه در یک معماری توزیع شده پیامگرا می گذردساخت: تولید کننده پیام را ایجاد و داده مورد نظر خودش را در آن قرار می دهد.ارسال: تولید کننده پیام را به کانال انتقال می دهد.تحویل: سیستم پیام گرا با مدیریت پیام دریافتی، آن را به مصرف کننده هدایت کرده و از دریافت آن اطمینان حاصل می کند.دریافت: دریافت کننده پیام را از کانال می خواندپردازش: دریافت کننده داده را از پیام استخراج کرده و آن را پردازش می کند.Messaging systemهمانطور که اشاره کردیم Messaging system در حقیقت مانند واسطی میان تولید کننده و مصرف کننده عمل می کند و مدیریت پیام ها را بر عهده دارد. در یک Messaging system باید قابلیت های زیر را وجود داشته باشد:کانال (Message Channel)پیام ها به دلایل مختلف و بین سرویس های متفاوت رد و بدل می شود. سرویس مقصد، قابلیت دریافت هر پیامی را ندارد زیرا برای هر کاربردی ساخته نشده است. سرویس پیامگرا مجموعه ای از اتصالات را دارد که برنامه های کاربردی را قادر می سازد با انتقال اطلاعات به روش های از پیش تعیین شده و قابل پیش بینی ارتباط برقرار کنند. در حقیقت سرویس ها از طریق کانال با یکدیگر ارتباط برقرار می کنند به طوری که تولید کننده داده را متناسب با نوع استفاده، در کانال مناسب قرار داده و مصرف کننده آنها را به همان شکلی که انتظار دارد از کانال می خواند. هر کانال برای کاربرد ویژه ای استفاده می شود.پیام (Message)سرویس ها برای تعامل با یکدیگر پیام رد و بدل می کنند. یک پیام از دو بخش اساسی تشکیل شده است:هدر (Header): اطلاعاتی که توسط سیستم پیامگرا استفاده می شود و داده های در حال انتقال، مبدا، مقصد و غیره را توصیف می کند.بدنه (Body): به طور کلی بدنه صرفا برای مصرف کننده در نظر گرفته می شود و سیستم پیامگرا در آن نقشی ندارد.ترتیب پذیری (Pipes and Process)در بسیاری از شرایط ممکن است که یک پیام به مجموعه ای از عملیات برای پردازش نیاز داشته باشد. فرض کنید پیامی از جانب کلاینت برای سرویس ما ارسال می شود. ما ابتدا باید آن را رمزگشایی کرده سپس عملیات احراز هویت برای آن مشتری را انجام داده و در نهایت با حذف پیام های تکراری و اسپم کار خودمان را ساده تر کنیم. اولین راه حل این است که تمام این نیازمندی ها را به صورت یکجا پیاده سازی کنیم. اما انعطاف پذیری را از دست می دهیم، امکان استفاده مجدد را نداریم و همچنین برای آزمون نرم افزار، دچار مشکل می شویم. راه حل دیگر این است که هر کدام از این نیازمندی ها را در مؤلفه های جداگانه پیاده سازی کنیم. با این وجود مشکل ما به طور کامل حل نمی شود. به عنوان مثال، در نظر بگیرید که مولفه احراز هویت برای عملکرد درست نیاز دارد تا پیام را به صورت رمزگشایی شده دریافت کند. در این شرایط مجبوریم مولفه ها را به صورت ترتیبی از مراحل پشت سرهم، ترکیب کنیم.یک سیستم پیامگرا باید این امکان را فراهم کند تا بتوانیم یک پردازش بزرگ را در قالب مجموعه ای از پردازش های کوچکتر (Process) و به صورت پشت سرهم (Pipe) انجام دهیم.مسیریابی (Message Router)مسیریاب پیام را در حقیقت می توان فیلتری در نظر گرفت که پیام را از کانال ورودی دریافت کرده و با توجه به مجموعه ای از شروط مشخص می کند که آن را برای کدام یک از کانال های خروجی هدایت کند. گفتیم که هر پیام علاوه بر بدنه می تواند مجموعه ای هدر ها را هم داشته باشد که یکی از مهمترین کاربرد آن ها در این قسمت می باشد. مسیریاب از این هدر ها استفاده کرده و آن را برای کانال مشخصی ارسال می کند.تبدیل کننده پیام (Message Translator)گفتیم که یکی از چالش های مهم ادغام میکروسرویس ها، پیاده سازی مختلف آنهاست. هر سرویس برداشت متفاوتی از &lt;&lt;مشتری&gt;&gt; خواهد داشت و به شکل جداگانه ای آن را پیاده سازی می کند. در این شرایط باید داده دریافتی را به شکل صحیح برای سرویس گیرنده تبدیل کنیم.تبدیل کننده پیام در حقیقت فیلتر مخصوصی است که داده دریافتی را به فرمت قابل قبول برای گیرنده تبدیل می کند.نقطه پایان (Message Endpoint)سرویس و سیستم پیامگرا دو مفهوم جداگانه هستند. سیستم های پیامگرا را می توان در حقیقت به عنوان یک سرور در نظر گرفت که وظیفه آن صرفا مدیریت پیام ها و هدایت آن ها به سمت مقصد می باشد. در حالی که سرویس چیزی از مفهوم پیام نمی داند و صرفا با داده خاصی کار می کند که از پیام استخراج می شود. سرویس ها در حالت عادی نمی دانند که چگونه از سیستم پیامگرا استفاده کنند. Message Endpoint در حقیقت واسطی است که به سرویس امکان بهره برداری از سیستم پیامگرا را می دهد. سرویس با استفاده از نقطه پایان، پیام ها را به کانال ارسال می کند یا از آن دریافت می کند.نگاهی جزئی تردر این قسمت برخی از خصوصیات بخش قبل را به صورت دقیق تر بررسی می کنیمکانال هادر حالت کلی کانال ها به به دو شکل میتوانند باشند:کانال همتا به همتاهمتا به همتا(Point to Point): در این نوع از کانال ها معمولا تعامل میان یک تولید کننده و یک مصرف کننده صورت می گیرد. در صورتی که چندین مصرف کننده بخواهند همزمان از کانال همتا به همتا استفاده کنند، در این صورت هر پیام داخل کانال فقط به وسیله یکی از مصرف کننده ها استفاده می شود.کانال پخشیپخشی(Publish-Subscribe): این نوع کانال معمولا به وسیله یک تولید کننده و چندین مصرف کننده استفاده می شود. هر مصرف کننده در حقیقت یک کپی از پیام داخل کانال را دریافت می کند.Channel Adapterنقطه پایان (Message Endpoint) واسط میان سرویس و سیستم پیامگرا می باشد و سرویس از طریق آن پیامی را به کانال ارسال می کند. آداپتور کانال در حقیقت برعکس عمل کرده و میان سیستم پیامگرا و سرویس عمل می کند. در یک معماری پیام گرا همه سرویس ها لزوما به وسیله خود شما توسعه داده نمی شود. برای مثال برای کار با یک پایگاه داده خاص یا بهره گیری از واسط های ارائه شده یک نرم افزار دیگر از آداپتور کانال استفاده می شود.سرویس ها به وسیله کانال با یکدیگر ارتباط دارند. سیستم های پیامگرای مختلف برای تعامل از پل پیام استفاده می کند. یک پل پیام در حقیقت از مجموعه ای از آداپتورها استفاده می کند که ارتباط میان سیستم های پیامگرا را تسهیل می کنند. کارگزاران پیام، نظیر ActiveMQ، Apache Kafka یا RabbitMQ به عنوان پل پیام استفاده می شوند.ساخت و ساز پیام در حالت کلی پیام های رد و بدل شده در معماری پیامگرا در سه دسته تقسیم می شوند:پیام فرمان (Command Message): برای فراخوانی روند در سرویس دیگر استفاده می شود. پیام داده (Document Message): داده خاصی را به سرویس دیگر ارسال می کند. مصرف کننده آزاد است که هر کاری با سند دریافتی انجام دهد.پیام رویداد (Event Message): به طور خاص برای کاربرد های آسنکرون استفاده می شود که تولید کننده وقوع رویدادی را به مصرف کننده اطلاع می دهد.  در بسیاری از شرایط نیاز است تا تولید کننده به ازای هر پیام ارسالی، پاسخی از گیرنده دریافت کند. به عنوان یک مثال ساده تولید کننده ای را در نظر بگیرید که از یک سرویس Restful استفاده می کند و طبعا برای هر درخواست به پاسخی نیاز دارد. برای پیاده سازی این حالت در معماری پیامگرا از یک کانال برای درخواست و کانال دیگر برای پاسخ استفاده می شود. نقطه پایان (Message Endpoint)مصرف کننده از طریق نقطه پایان، با سرویس پیامگرا تعامل داشته و پیام ها را دریافت می کند. نقطه پایان ها برای مصرف کننده دو حالت را فراهم می کنند:مصرف کننده رویداد محور (Event Driven Consumer): که به عنوان دریافت کننده آسنکرون هم شناخته می شود. در این حالت مصرف کننده منتظر دریافت پیام بوده و بلافاصله پس از دریافت، آن را پردازش می کند.مصرف کننده خودمختار (Polling Consumer): دریافت کننده سنکرون که برای گرفتن پیام از یک ساختار خارجی استفاده می شود (برای مثال یک پایگاه داده یا استفاده از واسط های نرم افزاری دیگر). در حقیقت  مصرف کننده، هر زمان که بخواهد پیامی را دریافت کرده و آن را پردازش می کند.مدیریت سیستم(System Management)در معماری پیامگرا مدیریت سیستم شامل موارد زیر می باشد: نظارت و کنترلبررسی و تجزیه تحلیل ترافیک پیام آزمون و رفع اشکالدر ادامه ویژگی های هر کدام را به صورت مختصر شرح می دهیمنظارت و کنترلدر حالت کلی، نظارت و کنترل شامل انجام کارهایی است که به منظور بررسی و کنترل یک سیستم پیامگرا انجام می شود. معمولا سیستم های پیامگرا توزیع شده هستند و نیازمند ساز و کاری هستیم که بتوانیم کنترل کاملی بر همه اجزاء داشته باشیم.Control Busگذرگاه کنترل (Control Bus)، امکان مدیریت کل سیستم را برای ما فراهم می کند. این رویکرد در حقیقت از همان مکانیزم کانال برای ارسال پیام استفاده می کند با این تفاوت که از کانال‌های جداگانه برای انتقال داده‌هایی استفاده می‌کند که مربوط به مدیریت اجزای درگیر در سیستم پیامگرا است.Detourدر شرایط خاصی ممکن است نیاز باشد که پردازش های اضافه تری را بر پیام ها انجام بدهیم (مثلا به دلایل رفع اشکال یا بررسی داده هایی که در یک کانال رد و بدل می شوند). در این حالت می توانیم با ایجاد یک انحراف(Detour) در کانال عملیات بیشتری را روی داده ها انجام بدهیم. اینکه مشخص کنیم چه زمانی و کدام پیام ها از کانال انحراف عبور کنند به کمک گذرگاه کنترل انجام می شود. تجزیه و تحلیل ترافیک پیامکانال نقطه به نقطه به طور معمول برای پیام های نوع داده استفاده می شود زیرا همانطور که گفتیم، این اطمینان وجود دارد که هر پیام صرفا به وسیله یک مصرف کننده استفاده می شود. با این وجود برای اهدافی مانند بازرسی پیام ها، آزمون و رفع خطا این کانال ها گزینه خوبی هستند. برای اینکه بتوانیم پیام های یک کانال را به صورت جداگانه بازرسی کنیم، معمولا با ایجاد یک کانال اضافه تر به وسیله Wire Tap، یک کپی از پیام داخلِ کانالِ فعلی، به کانال دیگری هدایت می شود تا بتوانیم حالت فعلی یک پیام را به خوبی بررسی کنیم.وابستگی کم از ویژگی های مهم یک معماری پیامگرا می باشد. مصرف کننده با دریافت پیام نمی داند که دقیقا کدام تولید کننده آن را ارسال کرده و پیام ها ساختار مشخصی داشته و به تولید کننده اش ارتباطی ندارد. این ویژگی به طور خاص رفع اشکال و آنالیز یک سیستم پیامگرا را با چالش هایی مواجه می کند چرا که دقیقا نمی دانیم که یک پیام چه مسیری را برای رسیدن به مقصد طی کرده است. چگونه می‌توانیم جریان پیام‌ها در یک سیستم را به طور مؤثر تجزیه و تحلیل و اشکال‌زدایی کنیم؟ برای حل این مشکل می توانیم در هر سرویس به پیام تاریخچه ای از آن را پیوست کنیم. این اطلاعات در هدر یک پیام ثبت می شود و در نهایت می دانیم که چه اتفاقاتی برای آن پیام در طول مسیر افتاده است.آزمون و رفع اشکالآزمون یک سیستم پیامگرا قبل از استقرار آن مهم است اما نباید صرفا به قبل از استقرار محدود شود. قابلیت پیام آزمون (Test Message) این امکان را برای ما فراهم می کند تا بتوانیم پس از استقرار نرم افزار عملکرد آن را زیر نظر داشته باشیم. در این رویکرد، پیامی صرفا برای بررسی عملکرد مولفه ها میان کانال های مختلف رد و بدل می شود. برای به کار بردن این الگوها نیاز به چارچوبی داریم که آن ها را از قبل پیاده سازی کرده باشد. در قسمت بعد سعی می کنیم یکی از مهمترین ابزارهای این رویکرد را به شما معرفی کنیم.</description>
                <category>محمد سپهر ملائی</category>
                <author>محمد سپهر ملائی</author>
                <pubDate>Fri, 22 Jul 2022 10:43:05 +0430</pubDate>
            </item>
                    <item>
                <title>مقدمه ای بر میکروسرویس ها</title>
                <link>https://virgool.io/@sepehrmsm1379/%D9%85%D9%82%D8%AF%D9%85%D9%87-%D8%A7%DB%8C-%D8%A8%D8%B1-%D9%85%D8%B9%D9%85%D8%A7%D8%B1%DB%8C-%D9%85%DB%8C%DA%A9%D8%B1%D9%88%D8%B3%D8%B1%D9%88%DB%8C%D8%B3-xologs54az9u</link>
                <description>در توسعه نرم افزار، ایده اصلی معماری میکروسرویس بر تجزیه عملکردی مبتنی است. به بیان ساده تر به جای توسعه یک برنامه بزرگ، آن را در قالب سرویس های جداگانه توسعه داده و با هم ادغام می کنیم. در صورت درک اولیه این مفهوم، ممکنه با ابهامات متعددی روبرو بشیم از جمله اینکه تعریف از سرویس چیست؟ اندازه یک سرویس چه قدر است؟ تعامل بین آنها چگونه انجام می شود؟ و ...برای پاسخ به این ابهامات لازمه که ابتدا با معماری نرم افزار آشنا بشیم. Chris Richardson در کتاب Microservices Patterns به این صورت تعریف مورد علاقه خودش رو از معماری نرم افزار بیان می کنه:معماری نرم افزار مجموعه ای از ساختارهای مورد نیاز برای موجودیتی است که شامل عناصر نرم افزاری، روابط بین آنها و ویژگی های هرکدام می باشد. از این تعریف می شود به خوبی برداشت کرد که یک نرم افزار می تواند از چندین بخش مستقل (سرویس) و روابط بین آنها تشکیل بشود. امروزه تجزیه پذیری یکی از مهمترین فاکتورهایی است که در توسعه نرم افزار در نظر گرفته می شود که به دلایل زیر اهمیت زیادی دارد:پیچیدگی کمتر و قابلیت نگهداری بیشتربه طور مستقل قابل استقرارتوسعه راحتتر و انعطاف پذیری بیشترتحمل خطای بالاتراستقلال تیم های توسعه برای هر سرویسامکان استفاده از ابزار های توسعه مختلف (زبان های برنامه نویسی و فریم وورک ها)اندازه یک میکروسرویس چه قدر باشد؟برای پاسخ به این ابهام ابتدا باید منظور خودمون رو از اندازه مشخص کنیم. آیا تعداد خط های کد می تواند معیار صحیحی برای اندازه باشه؟ به نظر نمی رسه که بتونه معیار درستی باشه در نظر بگیرید یک پیاده سازی ساده اگر برای Java تعداد 25 خط کد نیاز داشته باشه در Clojure به سادگی در 10 خط انجام میشه. سم نیومن در کتاب Building Microservices نقل قول جالبی از James Lewis بیان کرده:یک میکروسرویس باید اندازه کَله من باشهدر نگاه اول شاید این دیدگاه یکم گنگ و بی معنی باشه اما در حقیقت بیانگر این نکته هست که اندازه یک میکروسرویس باید به قدری باشه که به خوبی قابل فهم باشه. به عبارت دیگر پیچیدگی مهمترین معیار برای سنجش اندازه یک میکروسرویس هست. این ویژگی به شدت به تیم شما بستگی داره که تا چه قدر بتونن با پیچیدگی ها کنار بیان. به عبارت دیگه برای تیمی با توسعه دهندگان حرفه ای تر، میتوان پیچیدگی بیشتری برای یک میکروسرویس تصور کرد.تعامل بین سرویس ها چگونه انجام میشود؟هدف نهایی تهیه واسط برنامه نویسی نرم افزار (API) می باشد. به گونه ای که سایر سرویس ها با استفاده از آن بتوانند تعامل مناسبی با سرویس کنونی برقرار کنند. در ادامه برخی از مهمترین رویکرد هایی که برای تعامل بین سرویس ها استفاده می شود خدمتتون بیان میکنیم.1. RESTانتقال بازنمودی حالت (Representational State Transfer) نوعی معماری نرم افزار است که مجموعه اصول و قواعدی را برای بهره وری از یک سرویس خاص در بستر وب فراهم می کند. داده، اهمیت خاصی در این سبک معماری دارد. می‌توانید داده را به عنوان موجودیتی تصور کنید که سرویس به خوبی از آن آگاه هست و اطلاعات آن ذخیره می کند (مانند مشتری). سرویس RESTful، حالت های مختلفی از یک داده را بر حسب درخواست دریافتی از سایر سرویس ها تولید کرده و با فرمت معینی (مثلا JSON) بر می‌گرداند. این ویژگی عملا امکان تجزیه پذیری نرم افزار را فراهم کرده و به سرویس ها اجازه می دهد که به خوبی زبان یکدیگر را بفهمند. بعضا دیده می شود که REST و HTTP به جای یکدیگر به کار برده می شوند. دقت کنید که HTTP در حقیقت یک پروتکل از لایه کاربرد شبکه است که امکان تبادل داده میان کلاینت و سرور را میسر می کند. در صورتی که REST مجموعه اصول و قواعدی را بیان می کند که برای معماری نرم افزار به کار برده می شود. یک سیستم RESTful، برای افزایش انعطاف پذیری از قواعد خاص HTTP شامل GET, POST, DELETE استفاده می کند. یادآوری این نکته مهم است که استفاده از پروتکل HTTP برای یک سیستم RESTful لازم نیست.2. GraphQLیکی از ایراداتی که به REST گرفته شد تعداد حالت های محدود برای نمایش داده است. برای توضیح بیشتر به مورد زیر توجه کنید:یک نرم افزار تلفن همراهی را تصور کنید که قصد دارد در یک صفحه، نمای کلی از آخرین سفارشات مشتری را نشان دهد. صفحه شامل پنج سفارش آخر مشتری است که فقط فیلد های خاص از هر سفارش را نشان می دهد. در حالت عادی برای بازیابی اطلاعات مورد نیاز، باید درخواست های متعددی به سرور زده بشود که در واقع باعث کاهش کارایی می شود.روش GraphQL این امکان را فراهم می کند که با استفاده از یک تک کوئری خاص، تمام اطلاعات مورد نیاز از سرور را به دست بیاورید بدون این که مجبور باشید چندین بار به روش های مختلف به سرور درخواست بزنید. با وجود این که GraphQL برای مصرف کننده یا کلاینت دست بازتری برای واکشی داده قرار می دهد اما میتواند موجب بار بیشتری در سمت سرور بشود.3. Message brokersاین روش به طور ویژه برای کاربردهای آسنکرون استفاده می شود. قبل از آن مثال زیر را برای درک تفاوت بین فراخوانی سنکرون و آسنکرون در نظر بگیرید:Response registerUser(User user) {
        Response response = userService.register(user);
        messageSender.send(response.getMessage());
        return response;
}واضح است که در این مثال ابتدا کاربری را در سامانه ثبت نام کرده سپس پیامی را (از طریق ایمیل، پیامک و ...) برای او ارسال می کنیم و در نهایت نتیجه نهایی را برای کاربر برمیگردانیم. نکته مهم در این مثال ارسال پیام است. اگر بخواهیم فراخوانی send از messageSender را به صورت سنکرون در نظر بگیریم در این صورت باید تا پایان فرایند ارسال پیام به کاربر منتظر مانده و سپس نتیجه را به او بازگشت دهیم. آیا برای برنامه سمت کاربر بهینه است که تا پایان ارسال پیام منتظر بماند تا در نهایت نتیجه را دریافت کند؟در مدل آسنکرون این مشکل برطرف میشود و با فراخوانی send دیگر تا پایان آن منتظر نمی مانیم و نتیجه را بلافاصله به برنامه سمت کاربر برمیگردانیم. برای پیاده سازی فراخوانی آسنکرون معمولا به این صورت عمل می شود که هر سرویس پیام (Message) را برای دیگر سرویس ها می فرستد. پیام یک مفهوم عمومی است که می‌تواند شامل درخواست، پاسخ یا رویدادی باشد که میان سرویس ها رد و بدل می شود. این پیام توسط فرستنده به کارگزار پیام (Message broker) ارسال می‌شود که در نهایت گیرنده آنها را از کارگزار دریافت می کند. کارگزاران برای مدیریت پیام ها ممکنه که از topic، queue و یا هردو استفاده کنند. صفصف queue: به طور ویژه برای مکالمه نقطه به نقطه استفاده میشود. تولید کنند پیام را در صف قرار داده و مصرف کننده آن را از صف می خواند. دقت کنید که با هر بار خواندن عملا آن پیام از آن صف برداشته می شود بنابراین اگر همزمان چندین سرویس بخواهند از یک صف مصرف کنند، به همه پیام ها دسترسی نخواهند داشت.تاپیکتاپیک topic: امکان اشتراک گذاری پیام میان چندین سرویس را فراهم می کند. هر مصرف کننده در حقیقت یک کپی از پیام داخل تاپیک را دریافت میکند. این مفهوم به طور گسترده ای در Apache Kafka استفاده می شود.ممکنه تا حالا از خودتون پرسیده باشین که اصلا کارگزار پیام چه مزیتی داره؟ چرا پیام ما مستقیم برای سرویس هدف ارسال نمی شه؟ برای رفع این ابهامات توجهتون رو به مزایای این کارگزاران جلب می کنیم:ضمانت تحویل: خیلی وقت ها شرایطی میتونه پیش بیاد که سرویس مقصد به هر دلیلی از دسترس خارج بشه در این صورت پیام های ارسالی دیگه به وسیله آن دریافت نمیشه و دچار مشکل میشیم. در این حالت کارگزاران با نگهداری پیام این امکان را فراهم میکند که سرویس مقصد هر زمان که تونست بتونه از آن استفاده بکنه.ضمانت ترتیب: البته این لزوما حتمی نیست بیشتر به نوع سرویس شما بستگی داره که آیا ترتیب پیام های ارسالی براش مهم هست یا نهامکان انجام تراکنش: کارگزاران این امکان رو فراهم می کنند که بتونیم یک سری از تراکنش هایی را روی داده هایی که داخل خودشون دارند انجام بدهیم. مثلا این که خودمون مستقیم پیام هایی را داخل آن ها ذخیره کنیم و یا بخوانیم.در خصوص ارتباط از طریق کارگزاران پیام، یکی از مهمترین مفاهیمی که مطرح هست الگوهای ادغام سازمانی (Enterprise integration patterns) هست که بیانگر مجموعه ای از الگوهای طراحی است که برای ادغام نرم افزار های موجود در یک سیستم تجاری استفاده می شود. این الگوها بر رویکرد ارتباط از طریق ارسال پیام، میانِ سرویس ها اشاره می کنند. در قسمت بعد سعی میکنیم بیشتر آن را بررسی کنیم.منابع:Microservices Patterns by Chris RichardsonBuilding Microservices, 2nd Edition by Sam Newman</description>
                <category>محمد سپهر ملائی</category>
                <author>محمد سپهر ملائی</author>
                <pubDate>Wed, 13 Jul 2022 20:43:05 +0430</pubDate>
            </item>
                    <item>
                <title>رهیافتی بر ORM در Hibernate</title>
                <link>https://virgool.io/javacup/%D8%B1%D9%87%DB%8C%D8%A7%D9%81%D8%AA%DB%8C-%D8%A8%D8%B1-orm-%D8%AF%D8%B1-hibernate-o3z2pp3s9b31</link>
                <description>سلام تو این پست قصد دارم در مورد (نگاشت اشیا به مدل رابطه ای با استفاده از Hibernate ) توضیحاتی  خدمتتون بدهم امیدوارم که براتون مفید واقع بشه...یکی از چالش های زبان های برنامه نویسی شی گرا برای کار با پایگاه داده های رابطه ای نگاشت اشیا به داده ها در جداول می باشد این مشکل به دلیل از ساختار متفاوت مدل رابطه ای و شی گرایی حاصل میشه برای درک بهتر مثال زیر رو در نظر میگیریم:فرض کنید کلاسی داریم با نام Student که دارای داده های (نام, نام خانوادگی, سن , شماره دانشجویی) می باشد به راحتی میتوانیم کلاس فوق را به جدولی به صورت زیر نگاشت کنیم:CREATE table student( 
name varchar(20),
last_name varchar(20), 
age Integer, 
id Integer PRIMARY key 
);خب این که کاری نداشت!؟مشکل اصلی وقتی هست که کلاس Student ما به یک سری از کلاس های دیگر وابستگی داشته باشد. مثال زیر را در نظر بگیرید:مدلی رابطه ای طراحی کنید که شامل موجودیت های زیر باشد:1. دانشجو:شامل نام، نام خانوادگی، سن، شناسه، کارت دانشجویی، گروه آموزشی و لیست دروس اخذ شده2. کارت دانشجویی:شامل تاریخ صدور و Serial Number3. گروه آموزشیشامل نام، شناسه، دانشجویان4. درسشامل نام درس، شناسه درس، تعداد واحد و لیست دانشجویان اخذ کننده درسو روابط به صورت زیر باشند:هر دانشجو فقط و فقط یک کارت دانشجویی داردهر کارت دانشجویی فقط و فقط به یک دانشجو تعلق داردهر تعداد دانشجو فقط و فقط در یک گروه عضویت دارندهر گروه شامل چندین دانشجو می باشدهر دانشجو تعدادی از دروس را اخذ کرده استهر درس به وسیله تعدادی دانشجو اخذ شده استهمونطور که می بینید نگاشت این موجودیت ها به سادگی مثال قبل نمی باشند. اینجاست که ما میتوانیم با استفاده از ORM مبتنی بر Hibernate بدون هیچ نیازی از دانش اولیه به مدل رابطه ای، پایگاه داده خودمون رو طراحی کنیم. با استفاده از Hibernate و استاندارد JPA می توانیم مدل خود را به صورت شی گرا طرحی کرده و نگاشت به مدل رابطه ای را به خود Hibernate واگذار کنیم. JPA انوتیشن هایی برای انواع روابط تعریف کرده که به بیان آن ها می پردازیم و سپس آن ها را در هدف خود به کار میبریم: @OneToOneاین انوتیشن برای مواقعی استفاده میشود که رابطه ما از نوع یک به یک باشد مثلا روابط:هر دانشجو فقط و فقط یک کارت دانشجویی دارد هر کارت دانشجویی فقط و فقط به یک دانشجو تعلق داردبا انوتیشن OneToOne مشخص میشوند2. @OneToManyبیانگر رابطه یک به چند می باشد مثال زیر آن را به خوبی بیان میکند:هر گروه شامل چندین دانشجو می باشد3. @ManyToOneرابطه چند به یک:هر تعداد دانشجو فقط و فقط در یک گروه عضویت دارند4. @ManyToManyرابطه چند به چند که مشابه رابطه یک به یک، دوطرفه است. در حقیقت هر کدام از مثال های زیر به تنهایی معنای (یک به چند) میدهند ولی در کنار هم بیانگر چند به چند هستند :هر دانشجو تعدادی از دروس را اخذ کرده استهر درس به وسیله تعدادی دانشجو اخذ شده استپیاده سازیبرای پیاده سازی مدل رابطه ای در مثال اصلی این پست، کافی است آن را به صورت شی گرا طراحی کرده و با استفاده از انوتیشن های ذکر شده روابط بین آن ها را بیان کنیم پس به شکل زیر پیاده سازی داده ها را انجام می دهیم:برای دانشجو@Entity
public class Student {
    @Id
    private int id;

    @Column
    private String name;

    @Column(name = &amp;quotlast_name&amp;quot)
    private String lastName;

    @Column
    private int age;

    @OneToOne
    @JoinColumn(name = &amp;quotstudent_card&amp;quot)
    private StudentCard studentCard;

    @ManyToOne
    @JoinColumn(name = &amp;quotgroup_id&amp;quot)
    private GrouB groub;

    @ManyToMany
    @JoinTable(
            name = &amp;quotstudent_course&amp;quot,
            joinColumns = @JoinColumn(name = &amp;quotstudent_id&amp;quot),
            inverseJoinColumns = @JoinColumn(name = &amp;quotcourse_id&amp;quot)
    )
    private List&lt;Course&gt; courseList;

...
}
کارت دانشجویی@Entity
@Table(name = &amp;quotstdeunt_card&amp;quot)
public class StudentCard {

    @Id
    private int serialNumber;

    @Column
    private Date IssueDate;

    @OneToOne(mappedBy = &amp;quotstudentCard&amp;quot)
    private Student student;

...
}
گروه@Entity
@Table
public class GrouB {

    @Id
    private int id;

    @Column
    private String name;

    @OneToMany(mappedBy = &amp;quotgroub&amp;quot)
    private List&lt;Student&gt; studentList;

...
}فقط برای این کلاس نکته ای که داریم اینه که سعی کنید نام هایی که برای کلاس یا فیلد ها انتخاب میکنید جزو کلمات رزرو شده SQL نباشند!(با خطای Syntax مواجه میشوید)درس@Entity
public class Course {

    @Id
    @Column(name = &amp;quotcourse_id&amp;quot)
    private int courseId;

    @Column(name = &amp;quotcourse_name&amp;quot)
    private String courseName;

    @Column(name = &amp;quotcourse_rating&amp;quot)
    private int courseRating;

    @ManyToMany(mappedBy = &amp;quotcourseList&amp;quot)
    private List&lt;Student&gt; studentList;

...
}استفاده از Entity@ برای هر کلاسی که قصد نگاشت آن را داریم الزامی است.در روابط ManyToMany همانطور که میبینید از JoinTable@ استفاده کرده ایم. این انوتیشن زمانی کاربرد دارد که بخواهیم روابط بین موجودیت ها را در جداول جداگانه توصیف کنیم پس Hibernate جدولی به نام  student_course با ستون های student_id و course_id برای ما ایجاد خواهد کرد.در نهایت Hibernate به شکل زیر اشیا را در پایگاه داده MariaDB نگاشت میکند:البته علاوه بر کلاس های اولیه که قبلا مشاهده کردید باید در فایل hibernate.cfg.xml فیلد hibernate.hbm2ddl.auto را برابر update قرار دهیم جزئیات بیشتر را میتونید در اینجا ببینیدتوجه کنید که Hibernate قابلیت های خیلی بیشتری از این دارد و اینجا صرفا مطالب محدودی از اون گفته شد.</description>
                <category>محمد سپهر ملائی</category>
                <author>محمد سپهر ملائی</author>
                <pubDate>Wed, 14 Apr 2021 20:47:31 +0430</pubDate>
            </item>
                    <item>
                <title>طراحی اپلیکیشن دسکتاپ با Javafx</title>
                <link>https://virgool.io/javacup/%D8%B7%D8%B1%D8%A7%D8%AD%DB%8C-%D8%A7%D9%BE%D9%84%DB%8C%DA%A9%DB%8C%D8%B4%D9%86-%D8%AF%D8%B3%DA%A9%D8%AA%D8%A7%D9%BE-%D8%A8%D8%A7-javafx-urj0c8snswyk</link>
                <description>سلام، تو این پست قصد دارم یک روال کلی از پروژه ساده دسکتاپ با javafx رو بهتون نشون بدم. برای اینکار میخوام یک Music player اولیه رو با این ابزار پیاده سازی کنم. خواهید دید که اصلا چیز سختی نیست و علاوه جذابیت خاص خودش به راحتی قابل انجام است.من از ابزار های زیر استفاده میکنم:JDK 8IntelliJ IDEA CommunityScene builderدو مورد اولی رو احتمال زیاد باهاشون آشنایی دارید، Scene builder ابزاری هست که به شما کمک میکنه جلوه بصری نرم افزار خودتون رو راحت تر پیاده سازی کنید. خروجی کد fxml میده که بعدا میتونید اون رو تو پروژه جاوا بارگیری کنید. 1. ساخت پروژه اولیهدر intellij از قسمت new project مستقیم javafx رو انتخاب کنید. برای شما پروژه ساده ای ایجاد میشود که در پکیج sample شامل controller.java , main.java, sample.fxml می باشد. میتونید به دلخواه خودتون ساختار پکیج بندی پروژه رو تغییر بدید که فعلا من اینجا برای سادگی از اینکار صرف نظر میکنم. 2. طراحی viewوارد محیط scene builder میشویم میتوانید اونو مستقیم روی سیستمتون نصب کنید یا اینکه از طریق intellij باهاش کار کنید. ترجیح من اینه که از روش اول استفاده کنم(امکانات بیشتری بهتون میده). Scene builderبه راحتی میتونید کامپوننت های مورد نیاز خودتون رو به صورت کشیدن و رها کردن به صفحه بندیتون اضافه کنید من برای کار خودم از موجودیت های زیر استفاده میکنم: AnchorPaneیکی از نگه دارنده ها در javafx هست که به شما کمک میکنه صفحه بندی مورد نظرتون رو بسازید. با استفاده از نگه دارنده ها میتونید کامپوننت ها (نظیر دکمه، تکست فیلد و نوار) رو به شکل خاصی نمایش بدید.2. ToolBarیک منوی خیلی ساده در اختیارتون قرار میده که در ابتدا فقط شامل یک دکمه هست از اون برای انتخاب موسیقی دلخواه استفاده میکنیم3. Sliderبرای نمایش وضعیت پخش موسیقی مورد نظر استفاده میکنیم(اینکه درحال حاضر در کدام قسمت زمانی پخش هستیم) همچنین باید بتوانیم با تغییر وضعیت آن، قسمت دلخواه خودمون رو بشنویم4. Textبرای نمایش ثانیه و دقیقه لحظه ای هنگام پخش استفاده میکنیم 5. Buttonیک دکمه ساده برای play و pauseخب تا اینجا کار اصلیمون رو هنوز شروع نکردیم ولی قبل از اون بیاید یه تغییر کوچیک تو صفحه ایجاد کنیم برای تغییر نوشته یک دکمه به راحتی میتونیم روی اون کلیک کرده و از منوی سمت راست با تغییر Text، متن داخل اون رو شخصی سازی کنیم ولی اگه بخوایم شکل به خصوصی (مثلا دایره ای ) به یکی از دکمه ها بدیم چی؟ یا مثلا رنگش رو چه طور عوض کنیم؟جاوا اف ایکس از نوعی css خاصی پشتیبانی میکنه که به ما این قابلیت رو میده ظاهر کاپوننت های خودمون رو شخصی سازی کنیم. این ویژگی به ما کمک میکنه تا رابط های کاربری با ظاهر چشم نوازی ایجاد کنیم (بر خلاف Swing که کامپوننت های قدیمیش واقعا تو ذوق آدم میزد :)  )در حال حاضر صرفا برای شروع روی دکمه روبروی slider کلیک کرده و از منوی سمت راست قسمت Style، ویژگی خاص fx-background-radius- را به 50% تغییر میدهیم. همچنین میتوانیم از کاراکتر های خاص html که از یونی کد های مختلف شناخته میشن برای دکمه ها استفاده کنیم.3. نوشتن کلاس Controllerاول از همه نیاز داریم به یک سری از کامپوننت های خودمون دسترسی داشته باشیم تا بتونیم تغییراتی رو هنگام اجرا اعمال کنیم پس ویژگی fx:id یکتایی به هر کدوم اختصاص میدیم. همچنین باید یکسری event (رویداد)هایی مشخص کنیم تا هنگام وقوع اونها بتونیم تغییرات را اعمال کنیم مثلا اینکه وقتی کاربر روی دکمه ای کلیک میکنه چه اتفاقی رخ بده یا اینکه موقع تغییر دادن مکان نمای slider بتونیم وضعیت پخش رو تغییر بدهیم. برای این کارها کافیه روی کامپوننت مورد نظر کلیک کرده و از قسمت سمت راست منوی code موارد زیر را تعریف کنیمکامپوننت هایی که برای آن ها شناسه تعیین میکنیم1. اسلایدر2. کلید پخش3. نمایشگر زمانرویداد ها1. Action event برای هر کدام از کلید های file و play2. همچنین یک on mouse dragged برای اسلایدرخب کارمون تقریبا با scene builder تموم شد بعد از اینکه view رو در مسیر پروژه به جای Sample.fxml کپی کردیم (فراموش نکنید ویژگی fx:controller رو در فایل fxml برابر مسیر و نام کلاس کنترلر قرار بدید)حالا باید کلاس controller خودمون رو بنویسیم برای اینکه کارمون یکم راحتتر بشه از محیط Scene builder مسیرView -&gt; Show Sample Controller Skeletonیک نسخه اولیه از کلاس کنترلر میگیریم که شامل کامپوننت ها و رویداد هایی است که تعریف کردیم. همگی را در کلاس Controller کپی میکنیمکامپوننت هایی که شناسه یکتایی بهشون دادیم همگی با انوتیشن FXML@ مشخص می شوند و نیازی به نمونه سازی اولیه ندارند.خب اینجا ما علاوه بر مواردی که در بالا با انوتیشن مشخص شده اند به یک سری کلاس های بیشتری هم نیاز داریم: MediaPlayer  File همچنین یک متغیر boolean برای تمایز بین حالت پخش و سکونpublic class Controller {

    @FXML 
    private Slider slider;

    @FXML 
    private Button playButton;

    @FXML 
    private Text timeLabel;

    private MediaPlayer mediaPlayer;

    private File file;

    private boolean isPlaying = false;
...
}

اگه بخوایم از دید کاربر به مساله نگاه کنیم برای شروع کار نیاز داریم فایل مورد نظرمون رو انتخاب کنیم یک پیاده سازی ابتدایی که میتوانیم ارائه دهیم در متد Action event برای کلید file:@FXML
void openFile&#40;ActionEvent event&#41; {

    FileChooser fileChooser = new FileChooser();
    fileChooser.setTitle(&amp;quotSelect your music&amp;quot);

    file = fileChooser.showOpenDialog(new Stage());

    Media media = new Media(file.toURI().toString());
    mediaPlayer = new MediaPlayer(media);

}هرچه بیشتر درگیر جزئیات شویم میتونیم این قطعه کد رو کاملتر کنیم مثلا در ادامه نیاز داریم که به media player بگیم که هنگام پخش مکان نمای اسلایدر رو در جای مناسب قرار بده پس در همین متد قطعه کد زیر را هم داریمmediaPlayer.setOnPlaying(new Runnable() {
    @Override
    public void run() {
        new Thread(()-&gt;{
            while (isPlaying){
                slider.setValue(mediaPlayer.getCurrentTime().toSeconds() / mediaPlayer.getStopTime().toSeconds() * 100);
                try {
                    Thread.currentThread().sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
});
میبینید که برای کارمون مجبور شدیم یک ترد(Thread) جدید هم ایجاد کنیم و در آخر برای اینکه تردمون همیشه درگیر نباشه یک sleep کوتاه هم براش میگذاریم (این کار باعث میشه تا بتونیم مکان نمای اسلایدر رو تغییر بدیم و گرنه تردمون زورش از ما خیلی بیشتر میشه ).برای Action event کلید play:@FXML
void playClicked(ActionEvent event) {
        if(isPlaying){
            mediaPlayer.pause();
            playButton.setText(&amp;quot⏵&amp;quot);
        }
        else{
            mediaPlayer.play();
            playButton.setText(&amp;quot||&amp;quot);
        }

        isPlaying = !isPlaying;
}
و همچنین برای رویداد کشیدن Slider:@FXML
public void sliderDragged(MouseEvent mouseEvent) {
    mediaPlayer.seek(new Duration(slider.getValue() * mediaPlayer.getStopTime().toSeconds() * 10));
}
توجه کنید که موارد بالا صرفا برای پیاده سازی اولیه میباشند. همونطور که گفتم هر چی بیشتر درگیر جزئیات بشیم کاملترش میکنیمسورس کد در گیتهاب</description>
                <category>محمد سپهر ملائی</category>
                <author>محمد سپهر ملائی</author>
                <pubDate>Sat, 10 Apr 2021 00:29:24 +0430</pubDate>
            </item>
                    <item>
                <title>اپکس مثل آب خوردن</title>
                <link>https://virgool.io/@sepehrmsm1379/%D8%A7%D9%BE%DA%A9%D8%B3-%D9%85%D8%AB%D9%84-%D8%A2%D8%A8-%D8%AE%D9%88%D8%B1%D8%AF%D9%86-qegkxvplmief</link>
                <description>حقیقت اینه که من هر وقت میخواستم اطلاعاتی از oracle apex به دست بیارم و یا از افرادی در موردش سوال میکردم، اکثریت اونو با apex legends که ظاهرا یک بازی هست اشتباه میگرفتند. این پست در مورد بازی خاصی نیست بلکه میخوام بهتون نشون بدم که درست کردن یک web application قدرتمند و کاربردی چه قدر میتونه به سادگی انجام بشه دریغ از یک خط کد زدن!!!!! البته قبلش باید یکم در موردش آشنا بشیم.اوراکل اپکس یک پلت فرم توسعه با کد کمه که به شما اجازه میده برنامه های سازمانی مقیاس پذیر و ایمن با ویژگی های کلاس جهانی رو در دیتابیس قدرمند اوراکل ایجاد کنید. ساده تر بگم قبل از اون شما وقتی میخواستید یک اپلیکیشن تحت وب بسازید، این دغدغه ها رو داشتید:دیتابیسفرانت اندبک اند امنیتو ...همونطور که گفتم اپکس یک پلتفرم low code هست که همه موارد بالا رو از قبل براتون پیاده سازی میکنه و به شما اجازه میده بیشتر روی منطق کاری که میخواید انجام بدید تمرکز کنید.حالا اینو چه طوری ازش استفاده کنیم؟خب برای استفاده ازش طبیعتا باید نصبش کنید ولی من بهتون میگم صبر کنید! راه بهتری هم وجود داره.خیلی کوتاه، مراحل نصبش اینطوریه که شما باید دیتابیس اوراکل رو روی سیستمتون نصب کنید و بعد از دانلود آخرین ورژن اپکس درگیر یکسری تنظیمات و کانفیگ های عجیب بشید که این هدف من نیست. خوشبختانه خود oracle این امکان رو برای شما فراهم کرده که با درخواست و ایجاد یک workspace کار خودتون رو با اپکس شروع کنید. حالا اصلا این workspace چیه؟؟ همونطور که از اسمش مشخصه workspace یک فضای کاری برای شما ایجاد می کنه که به شما اجازه میده به راحتی اپلیکیشن های خودتون رو مدیریت کنید و قسمت های مختلف پروژه هاتون رو بسازید.وارد اینجا شوید در این صفحه به راحتی میتوانید اطلاعات خوبی رو از oracle apex به دست بیارید. از قسمت دوم گزینه request a free workspace رو بزنید تا مراحل ایجاد workspace رو شروع کنید.بعد از پرکردن فیلدهای صفحه اول سوالات ساده ای ازتون پرسیده میشه که مشکلی رو براتون به وجود نمیاره. در نهایت بعد از گذشت زمان کمی ایمیلی براتون ارسال میشه که با اون میتونید کارتون رو به راحتی شروع کنید. دقت کنید موقع ورود از شما رمز جدید میخواد که نباید اونو فراموش کنید.تبریک شما اولین workspace خودتون رو ایجاد کردید. در پست های بعدی سعی میکنم در مورد محیط اپکس و اینکه اصلا چه طوری باهاش کار میکنند توضیحات بیشتری بدهم.</description>
                <category>محمد سپهر ملائی</category>
                <author>محمد سپهر ملائی</author>
                <pubDate>Tue, 29 Dec 2020 23:19:28 +0330</pubDate>
            </item>
            </channel>
</rss>