### Example: Activate Biz B and Install Biz C Source: https://www.sofastack.tech/projects/sofa-boot/sofa-ark-zk-config Example of a Zookeeper configuration command to activate Biz B version 1.0, install Biz C version 1.0 with a specified URL, and ensure Biz B 1.0 remains activated. ```string B:1.0:Activated;C:1.0:Activated?bizUrl=urlC ``` -------------------------------- ### Example: Activate Biz B 2.0, Deactivate Biz B 1.0, Install Biz C Source: https://www.sofastack.tech/projects/sofa-boot/sofa-ark-zk-config This command demonstrates activating a new version of Biz B (2.0) while deactivating an older version (1.0), and installing Biz C. It highlights that only one version of a Biz can be active at a time. ```string B:1.0:Deactivated;B:2.0:Actaivated?bizUrl=urlB;C:1.0:Activated ``` -------------------------------- ### SOFABoot Application Startup Log Example Source: https://www.sofastack.tech/projects/sofa-boot/quick-start Example log output during the startup of a SOFABoot application. This indicates that the Tomcat server has started successfully on the default port. ```log 2018-04-05 21:36:26.572 INFO ---- Initializing ProtocolHandler ["http-nio-8080"] 2018-04-05 21:36:26.587 INFO ---- Starting ProtocolHandler [http-nio-8080] 2018-04-05 21:36:26.608 INFO ---- Using a shared selector for servlet write/read 2018-04-05 21:36:26.659 INFO ---- Tomcat started on port(s): 8080 (http) ``` -------------------------------- ### Ark Package MANIFEST.MF Example Source: https://www.sofastack.tech/projects/sofa-boot/sofa-ark-ark-jar Shows an example of the META-INF/MANIFEST.MF file within an Ark package, highlighting the Main-Class entry point. ```text Manifest-Version: 1.0 web-context-path: / Archiver-Version: Plexus Archiver Built-By: qilong.zql Ark-Biz-Name: sofa-ark-sample-springboot-ark Sofa-Ark-Version: 0.6.0 deny-import-packages: priority: 100 Main-Class: com.alipay.sofa.ark.bootstrap.ArkLauncher deny-import-classes: Ark-Container-Root: SOFA-ARK/container/ deny-import-resources: Ark-Biz-Version: 0.6.0 Created-By: Apache Maven 3.2.5 Build-Jdk: 1.8.0_101 ``` -------------------------------- ### Start Ark Biz Module Source: https://www.sofastack.tech/projects/sofa-boot/sofa-ark-dynamic-deploy Starts an Ark Biz module by setting the context classloader, running the main class, publishing startup events, and managing the Biz state based on activation configurations. ```Java public void start(String[] args) throws Throwable { ... ClassLoader oldClassLoader = ClassLoaderUtils.pushContextClassLoader(this.classLoader); // 1 EventAdminService eventAdminService = ArkServiceContainerHolder.getContainer().getService(EventAdminService.class); try { eventAdminService.sendEvent(new BeforeBizStartupEvent(this)); resetProperties(); if (!isMasterBizAndEmbedEnable()) { ... // 2 MainMethodRunner mainMethodRunner = new MainMethodRunner(mainClass, args); mainMethodRunner.run(); // this can trigger health checker handler eventAdminService.sendEvent(new AfterBizStartupEvent(this)); // 3 ... } } catch (Throwable e) { bizState = BizState.BROKEN; // 4 throw e; } finally { ClassLoaderUtils.popContextClassLoader(oldClassLoader); // 5 } BizManagerService bizManagerService = ArkServiceContainerHolder.getContainer().getService(BizManagerService.class); // 6 if (Boolean.getBoolean(Constants.ACTIVATE_NEW_MODULE)) { Biz currentActiveBiz = bizManagerService.getActiveBiz(bizName); if (currentActiveBiz == null) { bizState = BizState.ACTIVATED; } else { ((BizModel) currentActiveBiz).setBizState(BizState.DEACTIVATED); bizState = BizState.ACTIVATED; } } else { // 7 if (bizManagerService.getActiveBiz(bizName) == null) { bizState = BizState.ACTIVATED; } else { bizState = BizState.DEACTIVATED; } } } ``` -------------------------------- ### BizCommand Install Biz Operation Source: https://www.sofastack.tech/projects/sofa-boot/sofa-ark-dynamic-deploy The installBiz method in BizCommand handles the installation of an Ark Biz. It constructs a BizOperation object, populating it with parameters derived from user input (either a URL or a name:version pair), and then invokes ArkClient.installOperation. ```java String installBiz() { ... BizOperation bizOperation = new BizOperation().setOperationType(BizOperation.OperationType.INSTALL); String param = parameters.toArray(new String[] {})[0]; try { // 2 URL url = new URL(param); bizOperation.putParameter(Constants.CONFIG_BIZ_URL, param); } catch (Throwable t) { String[] nameAndVersion = param.split(Constants.STRING_COLON); if (nameAndVersion.length != 2) { LOGGER.error("Invalid telnet biz install command {}", param); return; } bizOperation.setBizName(nameAndVersion[0]).setBizVersion(nameAndVersion[1]); } try { ArkClient.installOperation(bizOperation); // 3 } catch (Throwable throwable) { LOGGER.error("Fail to process telnet install command: " + param, throwable); } ... } ``` -------------------------------- ### Parsing Archives and Installing Plugins Source: https://www.sofastack.tech/projects/sofa-boot/sofa-ark-startup-process This snippet shows the process of creating a master biz and installing plugins during the archive parsing stage. It involves classloaders, biz factories, and plugin factories. ```java // HandleArchiveStage 类 protected void processEmbed(PipelineContext pipelineContext) throws Exception { // 获取到 Launcher$AppClassLoader ClassLoader masterBizClassLoader = pipelineContext.getClass().getClassLoader(); // 创建 master biz Biz masterBiz = bizFactoryService.createEmbedMasterBiz(masterBizClassLoader); bizManagerService.registerBiz(masterBiz); ArkClient.setMasterBiz(masterBiz); ArkConfigs.putStringValue(Constants.MASTER_BIZ, masterBiz.getBizName()); ExecutableArchive executableArchive = pipelineContext.getExecutableArchive(); // 获取 plugin 包 List pluginArchives = executableArchive.getPluginArchives(); for (PluginArchive pluginArchive : pluginArchives) { // jar 包里面带有 com/alipay/sofa/ark/plugin/mark 文件的都是 plugin Plugin plugin = pluginFactoryService.createEmbedPlugin(pluginArchive, masterBizClassLoader); if (!isPluginExcluded(plugin)) { pluginManagerService.registerPlugin(plugin); } else { LOGGER.warn(String.format("The plugin of %s is excluded.", plugin.getPluginName())); } } return; } // BizFactoryServiceImpl 类 public Biz createEmbedMasterBiz(ClassLoader masterClassLoader) { BizModel bizModel = new BizModel(); bizModel.setBizState(BizState.RESOLVED).setBizName(ArkConfigs.getStringValue(MASTER_BIZ)) .setBizVersion("1.0.0").setMainClass("embed main").setPriority("100") .setWebContextPath("/").setDenyImportPackages(null).setDenyImportClasses(null) .setDenyImportResources(null).setInjectPluginDependencies(new HashSet<>) .setInjectExportPackages(null) .setClassPath(((URLClassLoader) masterClassLoader).getURLs()) .setClassLoader(masterClassLoader); return bizModel; } // EmbedClassPathArchive 类 @Override public List getPluginArchives() throws Exception { // 扫描 plugin 包,ARK_PLUGIN_MARK_ENTRY="com/alipay/sofa/ark/container/mark" List urlList = filterUrls(Constants.ARK_PLUGIN_MARK_ENTRY); List pluginArchives = new ArrayList<>(); for (URL url : urlList) { pluginArchives.add(new JarPluginArchive(getUrlJarFileArchive(url))); } return pluginArchives; } ``` -------------------------------- ### ArkContainer Start Method Source: https://www.sofastack.tech/projects/sofa-boot/sofa-ark-startup-process The `start` method in `ArkContainer` initializes the container, registers a shutdown hook, prepares configuration, and starts the service container. It then retrieves and executes the `Pipeline`. ```java public class ArkContainer { // ...... public Object start() throws ArkRuntimeException { AssertUtils.assertNotNull(arkServiceContainer, "arkServiceContainer is null !"); if (started.compareAndSet(false, true)) { Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { @Override public void run() { stop(); } })); prepareArkConfig(); reInitializeArkLogger(); arkServiceContainer.start(); // Pipeline pipeline = arkServiceContainer.getService(Pipeline.class); // pipeline.process(pipelineContext); // Ark System.out.println("Ark container started in " + (System.currentTimeMillis() - start) //NOPMD + " ms."); } return this; } // ...... } ``` -------------------------------- ### Install Spring Boot Biz Application Source: https://www.sofastack.tech/projects/sofa-boot/sofa-ark-spring-boot-demo Use the Telnet command to install a Spring Boot biz JAR. Specify the local path to the JAR file, prefixed with 'file:\\' for Windows or 'file:///' for macOS. ```bash sofa-ark>biz -i file:\\\\{本地目录}\\\\spring-boot-ark-biz\\\\target\\\\spring-boot-ark-biz-0.0.1-SNAPSHOT-ark-biz.jar ``` ```bash sofa-ark>biz -i file:///{本地目录}/spring-boot-ark-biz/target/spring-boot-ark-biz-0.0.1-SNAPSHOT-ark-biz.jar ``` -------------------------------- ### SOFAArk Dynamic Log Configuration Example Source: https://www.sofastack.tech/projects/sofa-boot/sofa-ark-ark-log This example shows the typical content of a SOFAArk dynamic log configuration file, which logs runtime dynamic configuration information. ```log sofa-ark/config-manage.log > sofa-ark 动态日志配置,打印 SOFAArk 运行时接受的动态配置信息,大概内容如下: ``` -------------------------------- ### Command-line startup for executable Ark JAR Source: https://www.sofastack.tech/projects/sofa-boot/sofa-ark-startup-process After packaging with the Maven plugin, you can start the Ark application directly from the command line using the 'java -jar' command. Replace placeholders with your actual business name and version. ```bash java -jar ${bizName}-${bizVersion}-executable-ark.jar ``` -------------------------------- ### Spring Boot Biz Application Output Source: https://www.sofastack.tech/projects/sofa-boot/sofa-ark-spring-boot-demo Example output after a Spring Boot biz application is successfully started within the SOFAArk container. ```text SpringBootArkBizApplication start! SpringBootArkBizApplication spring boot version: 2.6.6 SpringBootArkBizApplication classLoader: com.alipay.sofa.ark.container.service.classloader.BizClassLoader@366c5b ``` -------------------------------- ### SOFAArk Runtime Error Log Example Source: https://www.sofastack.tech/projects/sofa-boot/sofa-ark-ark-log This log snippet shows a typical error encountered during SOFAArk startup, indicating an issue with starting the web server or embedded Tomcat. ```log 2019-03-12 16:38:41,873 ERROR main - Start biz: Startup In IDE meet error java.lang.reflect.InvocationTargetException: null at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at com.alipay.sofa.ark.bootstrap.MainMethodRunner.run(MainMethodRunner.java:48) at com.alipay.sofa.ark.container.model.BizModel.start(BizModel.java:207) at com.alipay.sofa.ark.container.service.biz.DefaultBizDeployer.deploy(DefaultBizDeployer.java:52) at com.alipay.sofa.ark.container.service.biz.BizDeployServiceImpl.deploy(BizDeployServiceImpl.java:55) at com.alipay.sofa.ark.container.pipeline.DeployBizStage.process(DeployBizStage.java:47) at com.alipay.sofa.ark.container.pipeline.StandardPipeline.process(StandardPipeline.java:75) at com.alipay.sofa.ark.container.ArkContainer.start(ArkContainer.java:135) at com.alipay.sofa.ark.container.ArkContainer.main(ArkContainer.java:96) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at com.alipay.sofa.ark.bootstrap.MainMethodRunner.run(MainMethodRunner.java:48) at com.alipay.sofa.ark.bootstrap.AbstractLauncher.launch(AbstractLauncher.java:97) at com.alipay.sofa.ark.bootstrap.AbstractLauncher.launch(AbstractLauncher.java:68) at com.alipay.sofa.ark.support.startup.SofaArkBootstrap.remain(SofaArkBootstrap.java:77) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at com.alipay.sofa.ark.support.thread.LaunchRunner.run(LaunchRunner.java:61) at java.lang.Thread.run(Thread.java:745) Caused by: org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat ``` -------------------------------- ### SOFABoot Application Startup Output Source: https://www.sofastack.tech/projects/sofa-boot/quick-start Expected console output after successfully starting the SOFABoot application, indicating successful JVM service invocation. ```text Hello, jvm service xml implementation. Hello, jvm service annotation implementation. Hello, jvm service service client implementation. ``` -------------------------------- ### View Installed Modules Source: https://www.sofastack.tech/projects/sofa-boot/sofa-ark-spring-boot-demo List all installed SOFAArk modules, including the host application and dynamically installed biz applications, along with their status. ```bash sofa-ark>biz -a ``` -------------------------------- ### Example: Uninstall Biz B 2.0, Activate Biz B 1.0, Uninstall Biz C Source: https://www.sofastack.tech/projects/sofa-boot/sofa-ark-zk-config This command shows how to uninstall Biz B version 2.0, activate Biz B version 1.0, and uninstall Biz C. SOFAArk infers the execution order to maintain service continuity. ```string B:1.0:Activated ``` -------------------------------- ### Command-line Startup for SOFAArk Embedded Mode Source: https://www.sofastack.tech/projects/sofa-boot/sofa-ark-startup-process After packaging, you can start the Ark Biz JAR directly using Java -jar with these parameters to enable embedded mode and specify the master biz. ```bash java -jar -Dsofa.ark.embed.enable=true -Dcom.alipay.sofa.ark.master.biz=${bizName} ${bizName}-${bizVersion}-ark-biz.jar ``` -------------------------------- ### IDEA Startup Parameters for SOFAArk Embedded Mode Source: https://www.sofastack.tech/projects/sofa-boot/sofa-ark-startup-process When starting locally in IDEA, include these JVM parameters to enable SOFAArk's embedded mode and specify the master biz. ```bash -Dsofa.ark.embed.enable=true -Dcom.alipay.sofa.ark.master.biz=${bizName} ``` -------------------------------- ### Ark Plugin Manifest File Example Source: https://www.sofastack.tech/projects/sofa-boot/sofa-ark-ark-plugin The MANIFEST.MF file records plugin metadata, including groupId, artifactId, version, activator class, and exported packages/classes/resources. ```properties Manifest-Version: 1.0 groupId: com.alipay.sofa artifactId: sample-ark-plugin version: 0.6.0 priority: 100 pluginName: sample-ark-plugin description: activator: com.alipay.sofa.ark.sample.activator.SamplePluginActivator import-packages: import-classes: import-resources: export-packages: com.alipay.sofa.ark.sample.common export-classes: com.alipay.sofa.ark.sample.facade.SamplePluginService export-resources: Sample_Resource_Exported ``` -------------------------------- ### Start Ark Service Container with Guice Source: https://www.sofastack.tech/projects/sofa-boot/sofa-ark-startup-process This method initializes the ArkServiceContainer using Guice. It loads service modules via Java SPI, creates the Guice injector, retrieves and initializes all ArkService implementations, and sets up ArkClient services. ```java public class ArkServiceContainer { private Injector injector; private List arkServiceList = new ArrayList<>(); private AtomicBoolean started = new AtomicBoolean(false); private AtomicBoolean stopped = new AtomicBoolean(false); private final String[] arguments; private static final ArkLogger LOGGER = ArkLoggerFactory.getDefaultLogger(); public ArkServiceContainer(String[] arguments) { this.arguments = arguments; } /** * Start Ark Service Container * @throws ArkRuntimeException * @since 0.1.0 */ public void start() throws ArkRuntimeException { if (started.compareAndSet(false, true)) { ClassLoader oldClassLoader = ClassLoaderUtils.pushContextClassLoader(getClass() .getClassLoader()); try { LOGGER.info("Begin to start ArkServiceContainer"); // Guice 是 Google开发的, 一个轻量级的依赖注入框架 injector = Guice.createInjector(findServiceModules()); // 从 guice 中查询所有 ArkService 实例 for (Binding binding : injector .findBindingsByType(new TypeLiteral() { })) { arkServiceList.add(binding.getProvider().get()); } Collections.sort(arkServiceList, new OrderComparator()); for (ArkService arkService : arkServiceList) { LOGGER.info(String.format("Init Service: %s", arkService.getClass().getName())); // 初始化 arkService,一共有 4 个 ArkService,分别是: // PluginDeployService:部署 plugin 的服务 // BizDeployService: 部署 biz 包的服务 // ClassLoaderService: ClassLoader 服务 // StandardTelnetServer: Telnet 工具服务 arkService.init(); } ArkServiceContainerHolder.setContainer(this); ArkClient.setBizFactoryService(getService(BizFactoryService.class)); ArkClient.setBizManagerService(getService(BizManagerService.class)); ArkClient.setInjectionService(getService(InjectionService.class)); ArkClient.setEventAdminService(getService(EventAdminService.class)); ArkClient.setArguments(arguments); LOGGER.info("Finish to start ArkServiceContainer"); } finally { ClassLoaderUtils.popContextClassLoader(oldClassLoader); } } } private List findServiceModules() throws ArkRuntimeException { try { List modules = new ArrayList<>(); // 通过 java spi 加载 Module for (AbstractArkGuiceModule module : ServiceLoader.load(AbstractArkGuiceModule.class)) { modules.add(module); } return modules; } catch (Throwable e) { throw new ArkRuntimeException(e); } } // ...... } ``` -------------------------------- ### Run SOFABoot Application with SOFAArk (IDEA) Source: https://www.sofastack.tech/projects/sofa-boot/upgrade_4_x Start your SOFABoot application in IDEA with specific JVM parameters to enable SOFAArk embedding and master biz configuration. ```bash IDEA 启动,注意需要添加启动参数:-Dsofa.ark.embed.enable=true -Dcom.alipay.sofa.ark.master.biz=${bizName} ``` -------------------------------- ### SOFAArk Container Startup Log Source: https://www.sofastack.tech/projects/sofa-boot/faq Verify that the SOFAArk container has started successfully by checking for this specific log message. Its presence indicates the container is operational. ```text Ark container started in xxx ms. ``` -------------------------------- ### Spring Context Installation and Refresh Logic Source: https://www.sofastack.tech/projects/sofa-boot/sofa-boot-context-isolation-mechanism-explained This snippet outlines the core logic for installing and refreshing Spring contexts within the SOFA Boot module system. It handles the creation of a SpringContextLoader and conditionally refreshes contexts in parallel or serially based on configuration. ```java SpringContextLoader springContextLoader = createSpringContextLoader(); installSpringContext(application, springContextLoader); if (sofaModuleProperties.isModuleStartUpParallel()) { refreshSpringContextParallel(application); } else { refreshSpringContext(application); } ``` -------------------------------- ### SofaBootRpcStartListener Event Handling Source: https://www.sofastack.tech/projects/sofa-boot/sofaboot-healthcheck-mechanism-explained This listener processes the SofaBootRpcStartEvent by starting SOFARPC servers and registering provider configurations. This ensures that RPC services are available only after the application is ready. ```java public void onApplicationEvent(SofaBootRpcStartEvent event) { ...... Collection allProviderConfig = providerConfigContainer .getAllProviderConfig(); if (!CollectionUtils.isEmpty(allProviderConfig)) { //start server serverConfigContainer.startServers(); } ...... //register registry providerConfigContainer.publishAllProviderConfig(); ...... } ``` -------------------------------- ### Spring Boot Maven Plugin MANIFEST.MF Content Source: https://www.sofastack.tech/projects/sofa-boot/sofa-ark-build-package-plugin Example content of the MANIFEST.MF file generated by the spring-boot-maven-plugin, showing key details like the Start-Class and Main-Class. ```properties Manifest-Version: 1.0 Archiver-Version: Plexus Archiver Built-By: rrz Start-Class: pers.masteryourself.tutorial.sofa.ark.maven.plugin.MavenP luginApplication Spring-Boot-Classes: BOOT-INF/classes/ Spring-Boot-Lib: BOOT-INF/lib/ Spring-Boot-Version: 2.1.4.RELEASE Created-By: Apache Maven 3.5.3 Build-Jdk: 1.8.0_101 Main-Class: org.springframework.boot.loader.JarLauncher ``` -------------------------------- ### Ark Framework Log Output Source: https://www.sofastack.tech/projects/sofa-boot/sofa-ark-ark-log This log output details the startup sequence of the Ark framework, including ZooKeeper connection status, registry context path management, and application installation operations. ```log 2019-03-01 16:16:36,583 INFO main - Registry context path: /sofa-ark/demo with mode: PERSISTENT. 2019-03-01 16:16:36,818 INFO Curator-ConnectionStateManager-0 - Reconnect to zookeeper, re-register config resource. 2019-03-01 16:16:36,839 WARN main - Context path has exists in zookeeper, path=/sofa-ark/demo 2019-03-01 16:16:36,839 INFO main - Registry context path: /sofa-ark/demo/xx.xx.xxx.xxx with mode: EPHEMERAL. 2019-03-01 16:16:36,850 INFO main - Subscribe ip config: /sofa-ark/demo/xx.xx.xxx.xxx. 2019-03-01 16:17:20,215 INFO main - Registry context path: /sofa-ark/demo with mode: PERSISTENT. 2019-03-01 16:17:20,297 INFO Curator-ConnectionStateManager-0 - Reconnect to zookeeper, re-register config resource. 2019-03-01 16:17:20,319 WARN main - Context path has exists in zookeeper, path=/sofa-ark/demo 2019-03-01 16:17:20,319 INFO main - Registry context path: /sofa-ark/demo/xx.xx.xxx.xxx with mode: EPHEMERAL. 2019-03-01 16:17:20,327 INFO main - Subscribe ip config: /sofa-ark/demo/xx.xx.xxx.xxx. 2019-03-01 16:17:20,414 INFO main - Start to process init app config: app-two:2.0.0:activated?bizUrl=http://sofa.open.alipay.net:8090/sofa/ark/app-two/2.0.0/app-two-2.0.0-ark-biz.jar 2019-03-01 16:17:20,417 INFO main - Execute biz operation: INSTALL app-two:2.0.0 2019-03-01 16:17:32,226 INFO main - Registry context path: /sofa-ark/demo with mode: PERSISTENT. 2019-03-01 16:17:32,292 INFO Curator-ConnectionStateManager-0 - Reconnect to zookeeper, re-register config resource. 2019-03-01 16:17:32,313 WARN main - Context path has exists in zookeeper, path=/sofa-ark/demo 2019-03-01 16:17:32,313 INFO main - Registry context path: /sofa-ark/demo/xx.xx.xxx.xxx with mode: EPHEMERAL. 2019-03-01 16:17:32,322 INFO main - Subscribe ip config: /sofa-ark/demo/xx.xx.xxx.xxx. 2019-03-01 16:17:37,295 INFO main - Start to process init app config: app-two:2.0.0:activated?bizUrl=http://sofa.open.alipay.net:8090/sofa/ark/app-two/2.0.0/app-two-2.0.0-ark-biz.jar 2019-03-01 16:17:37,298 INFO main - Execute biz operation: INSTALL app-two:2.0.0 2019-03-01 16:18:24,291 INFO main-EventThread - Receive app config data: , version is 34. 2019-03-01 16:18:24,352 INFO SOFA-ARK-app-zookeeper-config-1-T1 - ConfigTask: app-zookeeper-config start to process config: 2019-03-01 16:18:24,352 INFO SOFA-ARK-app-zookeeper-config-1-T1 - Execute biz operation: UNINSTALL app-two:2.0.0 ``` -------------------------------- ### SOFABoot Module Properties Example Source: https://www.sofastack.tech/projects/sofa-boot/sofaboot-module Defines the SOFABoot module name, parent Spring context, required modules, and profile. Ensure Module-Name is unique across all SOFABoot modules in an application. ```properties Module-Name=com.alipay.test.biz.service.impl Spring-Parent=com.alipay.test.common.dal Require-Module=com.alipay.test.biz.shared Module-Profile=dev ``` -------------------------------- ### SOFAArk Maven Plugin MANIFEST.MF Content Source: https://www.sofastack.tech/projects/sofa-boot/sofa-ark-build-package-plugin Example content of the MANIFEST.MF file generated by the sofa-ark-maven-plugin, detailing Ark Biz name, version, and the ArkLauncher as the Main-Class. ```properties Manifest-Version: 1.0 web-context-path: / Archiver-Version: Plexus Archiver Built-By: rrz Ark-Biz-Name: tutorial-sofa-ark-maven-plugin Sofa-Ark-Version: 1.1.1 deny-import-packages: priority: 100 Main-Class: com.alipay.sofa.ark.bootstrap.ArkLauncher deny-import-classes: Ark-Container-Root: SOFA-ARK/container/ deny-import-resources: Ark-Biz-Version: 1.0.0-SNAPSHOT Created-By: Apache Maven 3.5.3 Build-Jdk: 1.8.0_101 ``` -------------------------------- ### RpcAfterHealthCheckCallback Implementation Source: https://www.sofastack.tech/projects/sofa-boot/sofaboot-healthcheck-mechanism-explained This implementation of ReadinessCheckCallback publishes SOFABoot RPC start events. It's triggered when the application is deemed ready, initiating RPC server startup and service registration. ```java public Health onHealthy(ApplicationContext applicationContext) { Health.Builder builder = new Health.Builder(); //rpc 开始启动事件监听器 applicationContext.publishEvent(new SofaBootRpcStartEvent(applicationContext)); //rpc 启动完毕事件监听器 applicationContext.publishEvent(new SofaBootRpcStartAfterEvent(applicationContext)); return builder.status(Status.UP).build(); } ``` -------------------------------- ### Use StartupSpringApplication for Startup Source: https://www.sofastack.tech/projects/sofa-boot/upgrade_4_x Launch your application using `StartupSpringApplication` to leverage SOFABoot's enhanced startup metrics. ```java public static void main(String[] args) { StartupSpringApplication startupSpringApplication = new StartupSpringApplication(Sofaboot4DemoApplication.class); startupSpringApplication.run(args); } ``` -------------------------------- ### Implement Sample JVM Service (XML) Source: https://www.sofastack.tech/projects/sofa-boot/quick-start Implementation of the SampleJvmService interface for publishing via XML configuration. ```java public class SampleJvmServiceImpl implements SampleJvmService { private String message; @Override public String message() { System.out.println(message); return message; } // getters and setters } ``` -------------------------------- ### Implement Sample JVM Service (Annotation) Source: https://www.sofastack.tech/projects/sofa-boot/quick-start Implementation of SampleJvmService with @SofaService annotation for publishing. ```java @SofaService(uniqueId = "annotationImpl") public class SampleJvmServiceAnnotationImpl implements SampleJvmService { @Override public String message() { String message = "Hello, jvm service annotation implementation."; System.out.println(message); return message; } } ``` -------------------------------- ### SofaArkBootstrap launch method Source: https://www.sofastack.tech/projects/sofa-boot/sofa-ark-startup-process The SofaArkBootstrap.launch method initiates the Ark startup sequence. It creates a new thread to execute the 'remain' method, which is responsible for launching the classpath. ```java public class SofaArkBootstrap { private static final String BIZ_CLASSLOADER = "com.alipay.sofa.ark.container.service.classloader.BizClassLoader"; private static final String MAIN_ENTRY_NAME = "remain"; private static EntryMethod entryMethod; public static void launch(String[] args) { try { if (!isSofaArkStarted()) { entryMethod = new EntryMethod(Thread.currentThread()); IsolatedThreadGroup threadGroup = new IsolatedThreadGroup( entryMethod.getDeclaringClassName()); // 参数中指定当前类的remain方法,LaunchRunner.run 里面会用反射调用remain方法 LaunchRunner launchRunner = new LaunchRunner(SofaArkBootstrap.class.getName(), MAIN_ENTRY_NAME, args); Thread launchThread = new Thread(threadGroup, launchRunner, entryMethod.getMethodName()); launchThread.start(); // 等待前面的线程执行完成 LaunchRunner.join(threadGroup); threadGroup.rethrowUncaughtException(); System.exit(0); } } catch (Throwable e) { throw new RuntimeException(e); } } private static void remain(String[] args) throws Exception {// NOPMD // 在一个新的线程里面执行该方法 AssertUtils.assertNotNull(entryMethod, "No Entry Method Found."); URL[] urls = getURLClassPath(); new ClasspathLauncher(new ClassPathArchive(entryMethod.getDeclaringClassName(), entryMethod.getMethodName(), urls)).launch(args, getClasspath(urls), entryMethod.getMethod()); } } ``` -------------------------------- ### Load Ark Biz via Command Line (Windows) Source: https://www.sofastack.tech/projects/sofa-boot/sofa-ark-ark-demo Use the 'biz -i' command with the JAR file path to load an Ark Biz on Windows systems. ```bash biz -i file:///C:/XXX/XXXX/target/**-ark-biz.jar ``` -------------------------------- ### Load Ark Biz via Command Line (Linux/MacOS) Source: https://www.sofastack.tech/projects/sofa-boot/sofa-ark-ark-demo Use the 'biz -i' command with the JAR file path to load an Ark Biz on Linux or MacOS systems. ```bash biz -i file:///XXX/XXXX/target/**-ark-biz.jar ``` -------------------------------- ### Add SOFABoot Runtime Starter Dependency Source: https://www.sofastack.tech/projects/sofa-boot/bean-async-init Include the `runtime-sofa-boot-starter` in your project's `pom.xml` to enable SOFABoot features. ```xml com.alipay.sofa runtime-sofa-boot-starter ``` -------------------------------- ### SOFA-ARK Container Dependency Source: https://www.sofastack.tech/projects/sofa-boot/sofa-ark-ark-jar Example Maven dependency configuration for the sofa-ark-all artifact, which is included in the Ark container. ```xml com.alipay.sofa sofa-ark-all ${sofa.ark.version} ``` -------------------------------- ### Get Annotation Key with Placeholder Replacement Source: https://www.sofastack.tech/projects/sofa-boot/upgrade_4_x Retrieve an annotation's key field, resolving placeholder values from the Spring Environment. ```java public String getAnnotationKey(Environment environment, DemoAnnotation demoAnnotation) { AnnotationWrapper serviceAnnotationWrapper = AnnotationWrapper.create(DemoAnnotation.class) .withEnvironment(environment) .withBinder(DefaultPlaceHolderBinder.INSTANCE); return serviceAnnotationWrapper.wrap(demoAnnotation).key(); } ``` -------------------------------- ### Launch SOFAArk Bootstrap in Main Method Source: https://www.sofastack.tech/projects/sofa-boot/sofa-ark-ark-demo Initialize the SOFAArk container by calling SofaArkBootstrap.launch(args) at the beginning of your application's main method. ```java public class Application{ public static void main(String[] args) { SofaArkBootstrap.launch(args); ... } } ``` -------------------------------- ### Get ExtensionClient using ExtensionClientAware Source: https://www.sofastack.tech/projects/sofa-boot/extension Implement ExtensionClientAware to easily obtain an instance of ExtensionClient. Define a Spring bean for the ExtensionClientBean class. ```java public class ExtensionClientBean implements ExtensionClientAware { private ExtensionClient extensionClient; @Override public void setExtensionClient(ExtensionClient extensionClient) { this.clientFactory = extensionClient; } public ExtensionClient getClientFactory() { return extensionClient; } } ``` -------------------------------- ### PluginActivator Interface Definition Source: https://www.sofastack.tech/projects/sofa-boot/sofa-ark-ark-service Defines the start and stop methods for a plugin's lifecycle. Implement this interface to manage plugin initialization and cleanup. ```java public interface PluginActivator { /** * Start Plugin * @param context plugin context * @throws ArkRuntimeException */ void start(PluginContext context); /** * Stop Plugin * @param context * @throws ArkRuntimeException */ void stop(PluginContext context); } ``` -------------------------------- ### AbstractLauncher Launch Method Source: https://www.sofastack.tech/projects/sofa-boot/sofa-ark-startup-process The `launch` method in `AbstractLauncher` is the entry point for executing a fat jar. It sets up the `ContainerClassLoader`, modifies the current thread's class loader, and initiates the `ArkContainer`. ```java public abstract class AbstractLauncher { /** * Launch the ark container. This method is the initial entry point when execute an fat jar. * @throws Exception if the ark container fails to launch. */ public Object launch(String[] args) throws Exception { JarFile.registerUrlProtocolHandler(); // ClassLoader classLoader = createContainerClassLoader(getContainerArchive()); List attachArgs = new ArrayList<>(); attachArgs .add(String.format("%s%s=%s", CommandArgument.ARK_CONTAINER_ARGUMENTS_MARK, CommandArgument.FAT_JAR_ARGUMENT_KEY, getExecutableArchive().getUrl() .toExternalForm())); attachArgs.addAll(Arrays.asList(args)); return launch(attachArgs.toArray(new String[attachArgs.size()]), getMainClass(), classLoader); } protected Object launch(String[] args, String mainClass, ClassLoader classLoader) throws Exception { ClassLoader old = Thread.currentThread().getContextClassLoader(); try { // Thread.currentThread().setContextClassLoader(classLoader); // return createMainMethodRunner(mainClass, args).run(); } finally { Thread.currentThread().setContextClassLoader(old); } } // ...... } ``` -------------------------------- ### Define Custom Startup Annotation Source: https://www.sofastack.tech/projects/sofa-boot/upgrade_4_x Define a custom annotation for use with SOFABoot's annotation wrapping capabilities. ```java @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER }) public @interface DemoAnnotation { String key() default ""; } ``` -------------------------------- ### Reference JVM Service on Bean Method Parameter with @SofaReference Source: https://www.sofastack.tech/projects/sofa-boot/sofa-ark-ark-jvm Starting from SOFABoot v2.6.0/v3.1.0, @SofaReference can be used on Bean Method parameters to reference JVM services. ```java @Configuration public class MultiSofaReferenceConfiguration { @Bean("sampleReference") TestService service(@Value("$spring.application.name") String appName, @SofaReference(uniqueId = "service") SampleService service) { return new TestService(service); } } ``` -------------------------------- ### Disable Module Parallel Startup Source: https://www.sofastack.tech/projects/sofa-boot/parallel-start To disable parallel module startup, add this property to your application.properties file. This ensures modules are started sequentially according to their dependencies. ```properties com.alipay.sofa.boot.module-start-up-parallel=false ``` -------------------------------- ### Sample Service Interface Source: https://www.sofastack.tech/projects/sofa-boot/sofa-ark-ark-jvm Defines a sample service interface for demonstration purposes. This interface and its dependencies must be packaged as an Ark Plugin for direct invocation. ```java public interface SampleService { Result service(); } ``` -------------------------------- ### SOFABoot Module Testing Source: https://www.sofastack.tech/projects/sofa-boot/quick-start Example of a unit test for SOFABoot modules using @SpringBootTest and @RunWith(SpringRunner.class). Demonstrates testing services referenced via @SofaReference. ```java @SpringBootTest @RunWith(SpringRunner.class) public class SofaBootWithModulesTest { @SofaReference private SampleJvmService sampleJvmService; @SofaReference(uniqueId = "annotationImpl") private SampleJvmService sampleJvmServiceAnnotationImpl; @SofaReference(uniqueId = "serviceClientImpl") private SampleJvmService sampleJvmServiceClientImpl; @Test public void test() { Assert.assertEquals("Hello, jvm service xml implementation.", sampleJvmService.message()); Assert.assertEquals("Hello, jvm service annotation implementation.", sampleJvmServiceAnnotationImpl.message()); Assert.assertEquals("Hello, jvm service service client implementation.", sampleJvmServiceClientImpl.message()); } } ``` -------------------------------- ### ArkContainer Main Method Source: https://www.sofastack.tech/projects/sofa-boot/sofa-ark-startup-process Handles parsing launch commands and initializing the ArkContainer. Supports both command-line execution and embedded modes. ```java public class ArkContainer { // ..... public static Object main(String[] args) throws ArkRuntimeException { if (args.length < MINIMUM_ARGS_SIZE) { throw new ArkRuntimeException("Please provide suitable arguments to continue !"); } try { LaunchCommand launchCommand = LaunchCommand.parse(args); if (launchCommand.isExecutedByCommandLine()) { ExecutableArkBizJar executableArchive; File rootFile = new File(URLDecoder.decode(launchCommand.getExecutableArkBizJar() .getFile())); if (rootFile.isDirectory()) { executableArchive = new ExecutableArkBizJar(new ExplodedArchive(rootFile)); } else { executableArchive = new ExecutableArkBizJar(new JarFileArchive(rootFile, launchCommand.getExecutableArkBizJar())); } return new ArkContainer(executableArchive, launchCommand).start(); } else { ClassPathArchive classPathArchive; if (ArkConfigs.isEmbedEnable()) { // Ark 2.0 内嵌模式 classPathArchive = new EmbedClassPathArchive(launchCommand.getEntryClassName(), launchCommand.getEntryMethodName(), launchCommand.getClasspath()); } else { classPathArchive = new ClassPathArchive(launchCommand.getEntryClassName(), launchCommand.getEntryMethodName(), launchCommand.getClasspath()); } return new ArkContainer(classPathArchive, launchCommand).start(); } } catch (IOException e) { throw new ArkRuntimeException(String.format("SOFAArk startup failed, commandline=%s", LaunchCommand.toString(args)), e); } } // ...... public Object start() throws ArkRuntimeException { AssertUtils.assertNotNull(arkServiceContainer, "arkServiceContainer is null !"); if (started.compareAndSet(false, true)) { Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { @Override public void run() { stop(); } })); prepareArkConfig(); reInitializeArkLogger(); // 启动容器服务 arkServiceContainer.start(); // 从容器服务中获取 Pipeline 实例,底层是从 Guice 中获取实例 Pipeline pipeline = arkServiceContainer.getService(Pipeline.class); // 执行流水线 pipeline.process(pipelineContext); // Ark 启动完成 System.out.println("Ark container started in " + (System.currentTimeMillis() - start) //NOPMD + " ms."); } return this; } } ``` -------------------------------- ### Publish JVM Service on Bean Method with @SofaService Source: https://www.sofastack.tech/projects/sofa-boot/sofa-ark-ark-jvm Starting from SOFABoot v2.6.0/v3.1.0, @SofaService can be applied to Bean Methods for publishing JVM services, allowing for unique IDs. ```java @Configuration public class SampleSofaServiceConfiguration { @Bean("sampleSofaService") @SofaService(uniqueId = "service1") SampleService service() { return new SampleServiceImpl(""); } } ``` -------------------------------- ### Add SOFABoot Dependencies Source: https://www.sofastack.tech/projects/sofa-boot/quick-start Includes necessary SOFABoot starters and module dependencies for the application. ```xml com.alipay.sofa isle-sofa-boot-starter com.alipay.sofa service-provider com.alipay.sofa service-consumer ``` -------------------------------- ### StandardPipeline Initialization and Processing Source: https://www.sofastack.tech/projects/sofa-boot/sofa-ark-startup-process The `StandardPipeline` class initializes a list of `PipelineStage`s and processes them sequentially. If any stage fails, the Ark startup process is terminated. ```java public class StandardPipeline implements Pipeline { private static final ArkLogger LOGGER = ArkLoggerFactory.getDefaultLogger(); private List stages = new ArrayList<>(); public StandardPipeline() { initializePipeline(); } private void initializePipeline() { // addPipelineStage( ArkServiceContainerHolder.getContainer().getService(HandleArchiveStage.class)) .addPipelineStage( ArkServiceContainerHolder.getContainer().getService(RegisterServiceStage.class)) .addPipelineStage( ArkServiceContainerHolder.getContainer().getService(ExtensionLoaderStage.class)) .addPipelineStage( ArkServiceContainerHolder.getContainer().getService(DeployPluginStage.class)) .addPipelineStage( ArkServiceContainerHolder.getContainer().getService(DeployBizStage.class)) .addPipelineStage( ArkServiceContainerHolder.getContainer().getService(FinishStartupStage.class)); } @Override public Pipeline addPipelineStage(PipelineStage pipelineStage) { stages.add(pipelineStage); return this; } @Override public void process(PipelineContext pipelineContext) throws ArkRuntimeException { for (PipelineStage pipelineStage : stages) { try { LOGGER.info(String.format("Start to process pipeline stage: %s", pipelineStage .getClass().getName())); // pipelineStage.process(pipelineContext); LOGGER.info(String.format("Finish to process pipeline stage: %s", pipelineStage .getClass().getName())); } catch (Throwable e) { LOGGER.error(String.format("Process pipeline stage fail: %s", pipelineStage .getClass().getName()), e); throw new ArkRuntimeException(e); } } } } ``` -------------------------------- ### XML Configuration for SOFABoot Service Publishing and Referencing Source: https://www.sofastack.tech/projects/sofa-boot/sofaboot-component-protocol-binding This XML snippet demonstrates how to publish and reference services using the `sofa:service` and `sofa:reference` tags with JVM binding in SOFABoot. ```xml ``` -------------------------------- ### Configuring Maven Plugin for Ark Plugin Packaging Source: https://www.sofastack.tech/projects/sofa-boot/sofa-ark-ark-plugin Configure the `sofa-ark-plugin-maven-plugin` within your Maven build to package your project as an Ark Plugin. This example shows how to bind the `ark-plugin` goal to an execution. ```xml com.alipay.sofa sofa-ark-plugin-maven-plugin ${sofa.ark.version} default-cli ark-plugin ``` -------------------------------- ### Add Support Starter Dependency for SOFAArk Source: https://www.sofastack.tech/projects/sofa-boot/sofa-ark-ark-demo For standard Java projects, use the sofa-ark-support-starter dependency to integrate with the SOFAArk container. ```xml com.alipay.sofa sofa-ark-support-starter ${sofa.ark.version} ``` -------------------------------- ### Run SOFABoot Application with SOFAArk (Command Line) Source: https://www.sofastack.tech/projects/sofa-boot/upgrade_4_x Execute the packaged SOFABoot application from the command line using Java, specifying SOFAArk embedding and master biz parameters. ```bash java -jar -Dsofa.ark.embed.enable=true -Dcom.alipay.sofa.ark.master.biz=${bizName} ${bizName}-${bizVersion}-ark-biz.jar ``` -------------------------------- ### Reference JVM Service using Programming API Source: https://www.sofastack.tech/projects/sofa-boot/sofa-ark-ark-jvm Get a ReferenceClient from the clientFactory, create a ReferenceParam, set the interface type, and then call the reference method to obtain a proxy for the JVM service. ```java ReferenceClient referenceClient=clientFactory.getClient(ReferenceClient.class); ReferenceParam referenceParam=new ReferenceParam(); referenceParam.setInterfaceType(SampleService.class); SampleService proxy=referenceClient.reference(referenceParam); ``` -------------------------------- ### Add Sample Ark Plugin Dependency Source: https://www.sofastack.tech/projects/sofa-boot/sofa-ark-ark-demo Include the sample-ark-plugin as a dependency in your project's pom.xml to integrate its functionality. ```xml com.alipay.sofa sample-ark-plugin ark-plugin ${sofa.ark.version} ```