Repository: skiptests/astraea
Pull request #392 (2022-06-05 14:48:23)

Add maven-publish plugin
這隻PR做了兩個改變：

1. 引入maven-publish plugin
2. 增添`app` prefix


Patch:
diff --git a/app/build.gradle b/app/build.gradle
index 55cca03a..654fd430 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -2,6 +2,7 @@ plugins {
     // Apply the application plugin to add support for building a CLI application in Java.
     id 'application'
     id 'com.github.johnrengelman.shadow' version '7.1.0'
+    id 'maven-publish'
 }
 
 repositories {
@@ -66,3 +67,21 @@ tasks.named('test') {
     minHeapSize = "512m"
     maxHeapSize = "2048m"
 }
+
+publishing {
+    publications {
+        mavenJava(MavenPublication) {
+            groupId = 'org.astraea'
+            from components.java
+        }
+    }
+    repositories {
+        maven {
+            url = "https://maven.pkg.github.com/skiptests/astraea"
+            credentials {
+                username = System.getenv("GITHUB_ACTOR")
+                password = System.getenv("GITHUB_TOKEN")
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/astraea/App.java b/app/src/main/java/org/astraea/app/App.java
similarity index 82%
rename from app/src/main/java/org/astraea/App.java
rename to app/src/main/java/org/astraea/app/App.java
index cf9ec3c3..eaa4f14f 100644
--- a/app/src/main/java/org/astraea/App.java
+++ b/app/src/main/java/org/astraea/app/App.java
@@ -1,18 +1,18 @@
-package org.astraea;
+package org.astraea.app;
 
 import com.beust.jcommander.ParameterException;
 import java.lang.reflect.InvocationTargetException;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
-import org.astraea.admin.ReplicaCollie;
-import org.astraea.admin.ReplicaSyncingMonitor;
-import org.astraea.admin.TopicExplorer;
-import org.astraea.automation.Automation;
-import org.astraea.cost.topic.PartitionScore;
-import org.astraea.metrics.MetricExplorer;
-import org.astraea.performance.Performance;
-import org.astraea.web.WebService;
+import org.astraea.app.admin.ReplicaCollie;
+import org.astraea.app.admin.ReplicaSyncingMonitor;
+import org.astraea.app.admin.TopicExplorer;
+import org.astraea.app.automation.Automation;
+import org.astraea.app.cost.topic.PartitionScore;
+import org.astraea.app.metrics.MetricExplorer;
+import org.astraea.app.performance.Performance;
+import org.astraea.app.web.WebService;
 
 public class App {
   private static final Map<String, Class<?>> MAIN_CLASSES =
diff --git a/app/src/main/java/org/astraea/admin/Admin.java b/app/src/main/java/org/astraea/app/admin/Admin.java
similarity index 99%
rename from app/src/main/java/org/astraea/admin/Admin.java
rename to app/src/main/java/org/astraea/app/admin/Admin.java
index 3ea172ad..eef5897b 100644
--- a/app/src/main/java/org/astraea/admin/Admin.java
+++ b/app/src/main/java/org/astraea/app/admin/Admin.java
@@ -1,4 +1,4 @@
-package org.astraea.admin;
+package org.astraea.app.admin;
 
 import java.io.Closeable;
 import java.util.Collection;
diff --git a/app/src/main/java/org/astraea/admin/Builder.java b/app/src/main/java/org/astraea/app/admin/Builder.java
similarity index 99%
rename from app/src/main/java/org/astraea/admin/Builder.java
rename to app/src/main/java/org/astraea/app/admin/Builder.java
index 0139bdd0..a602d38b 100644
--- a/app/src/main/java/org/astraea/admin/Builder.java
+++ b/app/src/main/java/org/astraea/app/admin/Builder.java
@@ -1,4 +1,4 @@
-package org.astraea.admin;
+package org.astraea.app.admin;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -33,7 +33,7 @@ import org.apache.kafka.common.quota.ClientQuotaAlteration;
 import org.apache.kafka.common.quota.ClientQuotaEntity;
 import org.apache.kafka.common.quota.ClientQuotaFilter;
 import org.apache.kafka.common.quota.ClientQuotaFilterComponent;
-import org.astraea.common.Utils;
+import org.astraea.app.common.Utils;
 
 public class Builder {
 
diff --git a/app/src/main/java/org/astraea/admin/Compression.java b/app/src/main/java/org/astraea/app/admin/Compression.java
similarity index 91%
rename from app/src/main/java/org/astraea/admin/Compression.java
rename to app/src/main/java/org/astraea/app/admin/Compression.java
index 1e1d7977..06be7b08 100644
--- a/app/src/main/java/org/astraea/admin/Compression.java
+++ b/app/src/main/java/org/astraea/app/admin/Compression.java
@@ -1,4 +1,4 @@
-package org.astraea.admin;
+package org.astraea.app.admin;
 
 import java.util.Locale;
 
diff --git a/app/src/main/java/org/astraea/admin/Config.java b/app/src/main/java/org/astraea/app/admin/Config.java
similarity index 94%
rename from app/src/main/java/org/astraea/admin/Config.java
rename to app/src/main/java/org/astraea/app/admin/Config.java
index 0011d661..7fd8d49f 100644
--- a/app/src/main/java/org/astraea/admin/Config.java
+++ b/app/src/main/java/org/astraea/app/admin/Config.java
@@ -1,4 +1,4 @@
-package org.astraea.admin;
+package org.astraea.app.admin;
 
 import java.util.Collection;
 import java.util.Map;
diff --git a/app/src/main/java/org/astraea/admin/ConsumerGroup.java b/app/src/main/java/org/astraea/app/admin/ConsumerGroup.java
similarity index 97%
rename from app/src/main/java/org/astraea/admin/ConsumerGroup.java
rename to app/src/main/java/org/astraea/app/admin/ConsumerGroup.java
index 2e3ff323..72b62d75 100644
--- a/app/src/main/java/org/astraea/admin/ConsumerGroup.java
+++ b/app/src/main/java/org/astraea/app/admin/ConsumerGroup.java
@@ -1,4 +1,4 @@
-package org.astraea.admin;
+package org.astraea.app.admin;
 
 import java.util.List;
 import java.util.Map;
diff --git a/app/src/main/java/org/astraea/admin/Member.java b/app/src/main/java/org/astraea/app/admin/Member.java
similarity index 98%
rename from app/src/main/java/org/astraea/admin/Member.java
rename to app/src/main/java/org/astraea/app/admin/Member.java
index 6eaad442..b3a9a347 100644
--- a/app/src/main/java/org/astraea/admin/Member.java
+++ b/app/src/main/java/org/astraea/app/admin/Member.java
@@ -1,4 +1,4 @@
-package org.astraea.admin;
+package org.astraea.app.admin;
 
 import java.util.Objects;
 import java.util.Optional;
diff --git a/app/src/main/java/org/astraea/admin/Offset.java b/app/src/main/java/org/astraea/app/admin/Offset.java
similarity index 93%
rename from app/src/main/java/org/astraea/admin/Offset.java
rename to app/src/main/java/org/astraea/app/admin/Offset.java
index ba13ba4a..7e7bf961 100644
--- a/app/src/main/java/org/astraea/admin/Offset.java
+++ b/app/src/main/java/org/astraea/app/admin/Offset.java
@@ -1,4 +1,4 @@
-package org.astraea.admin;
+package org.astraea.app.admin;
 
 public final class Offset {
   private final long earliest;
diff --git a/app/src/main/java/org/astraea/admin/ProducerState.java b/app/src/main/java/org/astraea/app/admin/ProducerState.java
similarity index 98%
rename from app/src/main/java/org/astraea/admin/ProducerState.java
rename to app/src/main/java/org/astraea/app/admin/ProducerState.java
index 966add47..e2f14cf7 100644
--- a/app/src/main/java/org/astraea/admin/ProducerState.java
+++ b/app/src/main/java/org/astraea/app/admin/ProducerState.java
@@ -1,4 +1,4 @@
-package org.astraea.admin;
+package org.astraea.app.admin;
 
 import java.util.Objects;
 
diff --git a/app/src/main/java/org/astraea/admin/Quota.java b/app/src/main/java/org/astraea/app/admin/Quota.java
similarity index 99%
rename from app/src/main/java/org/astraea/admin/Quota.java
rename to app/src/main/java/org/astraea/app/admin/Quota.java
index ae9fb62c..36fbac7a 100644
--- a/app/src/main/java/org/astraea/admin/Quota.java
+++ b/app/src/main/java/org/astraea/app/admin/Quota.java
@@ -1,4 +1,4 @@
-package org.astraea.admin;
+package org.astraea.app.admin;
 
 import java.util.Arrays;
 import java.util.Collection;
diff --git a/app/src/main/java/org/astraea/admin/QuotaCreator.java b/app/src/main/java/org/astraea/app/admin/QuotaCreator.java
similarity index 97%
rename from app/src/main/java/org/astraea/admin/QuotaCreator.java
rename to app/src/main/java/org/astraea/app/admin/QuotaCreator.java
index f2a82968..d4e3cc51 100644
--- a/app/src/main/java/org/astraea/admin/QuotaCreator.java
+++ b/app/src/main/java/org/astraea/app/admin/QuotaCreator.java
@@ -1,4 +1,4 @@
-package org.astraea.admin;
+package org.astraea.app.admin;
 
 /**
  * Kafka quota APIs are too incomprehensible to use, so we re-design quota APIs to builder pattern.
diff --git a/app/src/main/java/org/astraea/admin/Replica.java b/app/src/main/java/org/astraea/app/admin/Replica.java
similarity index 98%
rename from app/src/main/java/org/astraea/admin/Replica.java
rename to app/src/main/java/org/astraea/app/admin/Replica.java
index 5a8ec623..3e88b24d 100644
--- a/app/src/main/java/org/astraea/admin/Replica.java
+++ b/app/src/main/java/org/astraea/app/admin/Replica.java
@@ -1,4 +1,4 @@
-package org.astraea.admin;
+package org.astraea.app.admin;
 
 import java.util.Objects;
 
diff --git a/app/src/main/java/org/astraea/admin/ReplicaCollie.java b/app/src/main/java/org/astraea/app/admin/ReplicaCollie.java
similarity index 97%
rename from app/src/main/java/org/astraea/admin/ReplicaCollie.java
rename to app/src/main/java/org/astraea/app/admin/ReplicaCollie.java
index 097b6bf8..32e95c2e 100644
--- a/app/src/main/java/org/astraea/admin/ReplicaCollie.java
+++ b/app/src/main/java/org/astraea/app/admin/ReplicaCollie.java
@@ -1,4 +1,4 @@
-package org.astraea.admin;
+package org.astraea.app.admin;
 
 import com.beust.jcommander.Parameter;
 import java.io.IOException;
@@ -10,9 +10,9 @@ import java.util.Map;
 import java.util.Set;
 import java.util.TreeMap;
 import java.util.stream.Collectors;
-import org.astraea.argument.BooleanField;
-import org.astraea.argument.IntegerSetField;
-import org.astraea.argument.StringSetField;
+import org.astraea.app.argument.BooleanField;
+import org.astraea.app.argument.IntegerSetField;
+import org.astraea.app.argument.StringSetField;
 
 public class ReplicaCollie {
   static final String UNKNOWN = "unknown";
@@ -287,7 +287,7 @@ public class ReplicaCollie {
   }
 
   public static void main(String[] args) throws IOException {
-    var argument = org.astraea.argument.Argument.parse(new Argument(), args);
+    var argument = org.astraea.app.argument.Argument.parse(new Argument(), args);
 
     try (var admin = Admin.of(argument.bootstrapServers())) {
       execute(admin, argument)
@@ -309,7 +309,7 @@ public class ReplicaCollie {
     }
   }
 
-  static class Argument extends org.astraea.argument.Argument {
+  static class Argument extends org.astraea.app.argument.Argument {
     @Parameter(
         names = {"--topics"},
         description = "Those topics' partitions will get reassigned. Empty means all topics",
diff --git a/app/src/main/java/org/astraea/admin/ReplicaMigrator.java b/app/src/main/java/org/astraea/app/admin/ReplicaMigrator.java
similarity index 97%
rename from app/src/main/java/org/astraea/admin/ReplicaMigrator.java
rename to app/src/main/java/org/astraea/app/admin/ReplicaMigrator.java
index 6ddf7477..90f0347d 100644
--- a/app/src/main/java/org/astraea/admin/ReplicaMigrator.java
+++ b/app/src/main/java/org/astraea/app/admin/ReplicaMigrator.java
@@ -1,4 +1,4 @@
-package org.astraea.admin;
+package org.astraea.app.admin;
 
 import java.util.List;
 import java.util.Map;
diff --git a/app/src/main/java/org/astraea/admin/ReplicaSyncingMonitor.java b/app/src/main/java/org/astraea/app/admin/ReplicaSyncingMonitor.java
similarity index 96%
rename from app/src/main/java/org/astraea/admin/ReplicaSyncingMonitor.java
rename to app/src/main/java/org/astraea/app/admin/ReplicaSyncingMonitor.java
index 816a861f..3a05a5b4 100644
--- a/app/src/main/java/org/astraea/admin/ReplicaSyncingMonitor.java
+++ b/app/src/main/java/org/astraea/app/admin/ReplicaSyncingMonitor.java
@@ -1,4 +1,4 @@
-package org.astraea.admin;
+package org.astraea.app.admin;
 
 import com.beust.jcommander.Parameter;
 import java.time.Duration;
@@ -16,17 +16,17 @@ import java.util.function.Supplier;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 import org.apache.kafka.common.TopicPartitionReplica;
-import org.astraea.argument.DurationField;
-import org.astraea.argument.NonEmptyStringField;
-import org.astraea.common.DataRate;
-import org.astraea.common.DataSize;
-import org.astraea.common.DataUnit;
-import org.astraea.common.Utils;
+import org.astraea.app.argument.DurationField;
+import org.astraea.app.argument.NonEmptyStringField;
+import org.astraea.app.common.DataRate;
+import org.astraea.app.common.DataSize;
+import org.astraea.app.common.DataUnit;
+import org.astraea.app.common.Utils;
 
 public class ReplicaSyncingMonitor {
 
   public static void main(String[] args) {
-    Argument argument = org.astraea.argument.Argument.parse(new Argument(), args);
+    Argument argument = org.astraea.app.argument.Argument.parse(new Argument(), args);
     try (Admin topicAdmin = Admin.of(argument.bootstrapServers())) {
       execute(topicAdmin, argument);
     }
@@ -297,7 +297,7 @@ public class ReplicaSyncingMonitor {
         .collect(Collectors.joining(", ", "[", "]"));
   }
 
-  static class Argument extends org.astraea.argument.Argument {
+  static class Argument extends org.astraea.app.argument.Argument {
 
     @Parameter(
         names = {"--topics"},
diff --git a/app/src/main/java/org/astraea/admin/TopicCreator.java b/app/src/main/java/org/astraea/app/admin/TopicCreator.java
similarity index 97%
rename from app/src/main/java/org/astraea/admin/TopicCreator.java
rename to app/src/main/java/org/astraea/app/admin/TopicCreator.java
index 46499b58..5dd71d74 100644
--- a/app/src/main/java/org/astraea/admin/TopicCreator.java
+++ b/app/src/main/java/org/astraea/app/admin/TopicCreator.java
@@ -1,4 +1,4 @@
-package org.astraea.admin;
+package org.astraea.app.admin;
 
 import java.time.Duration;
 import java.util.Map;
diff --git a/app/src/main/java/org/astraea/admin/TopicExplorer.java b/app/src/main/java/org/astraea/app/admin/TopicExplorer.java
similarity index 98%
rename from app/src/main/java/org/astraea/admin/TopicExplorer.java
rename to app/src/main/java/org/astraea/app/admin/TopicExplorer.java
index 4c3cfb21..4274cc62 100644
--- a/app/src/main/java/org/astraea/admin/TopicExplorer.java
+++ b/app/src/main/java/org/astraea/app/admin/TopicExplorer.java
@@ -1,4 +1,4 @@
-package org.astraea.admin;
+package org.astraea.app.admin;
 
 import com.beust.jcommander.Parameter;
 import java.io.IOException;
@@ -17,10 +17,10 @@ import java.util.function.Function;
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
 import java.util.stream.Stream;
-import org.astraea.argument.NonEmptyStringField;
-import org.astraea.argument.StringSetField;
-import org.astraea.common.DataSize;
-import org.astraea.common.DataUnit;
+import org.astraea.app.argument.NonEmptyStringField;
+import org.astraea.app.argument.StringSetField;
+import org.astraea.app.common.DataSize;
+import org.astraea.app.common.DataUnit;
 
 public class TopicExplorer {
 
@@ -109,7 +109,7 @@ public class TopicExplorer {
   }
 
   public static void main(String[] args) throws IOException {
-    var argument = org.astraea.argument.Argument.parse(new Argument(), args);
+    var argument = org.astraea.app.argument.Argument.parse(new Argument(), args);
     try (var admin = Admin.of(argument.bootstrapServers())) {
       var result = execute(admin, argument.topics.isEmpty() ? admin.topicNames() : argument.topics);
       TreeOutput.print(result, System.out);
@@ -446,7 +446,7 @@ public class TopicExplorer {
     }
   }
 
-  static class Argument extends org.astraea.argument.Argument {
+  static class Argument extends org.astraea.app.argument.Argument {
     @Parameter(
         names = {"--topics"},
         description = "the topics to show all offset-related information. Empty means all topics",
diff --git a/app/src/main/java/org/astraea/admin/TopicPartition.java b/app/src/main/java/org/astraea/app/admin/TopicPartition.java
similarity index 98%
rename from app/src/main/java/org/astraea/admin/TopicPartition.java
rename to app/src/main/java/org/astraea/app/admin/TopicPartition.java
index ecb45d1e..a6f0eaa3 100644
--- a/app/src/main/java/org/astraea/admin/TopicPartition.java
+++ b/app/src/main/java/org/astraea/app/admin/TopicPartition.java
@@ -1,4 +1,4 @@
-package org.astraea.admin;
+package org.astraea.app.admin;
 
 import java.util.Objects;
 
diff --git a/app/src/main/java/org/astraea/argument/Argument.java b/app/src/main/java/org/astraea/app/argument/Argument.java
similarity index 98%
rename from app/src/main/java/org/astraea/argument/Argument.java
rename to app/src/main/java/org/astraea/app/argument/Argument.java
index 30d7a0e4..e6f588f1 100644
--- a/app/src/main/java/org/astraea/argument/Argument.java
+++ b/app/src/main/java/org/astraea/app/argument/Argument.java
@@ -1,4 +1,4 @@
-package org.astraea.argument;
+package org.astraea.app.argument;
 
 import com.beust.jcommander.JCommander;
 import com.beust.jcommander.Parameter;
diff --git a/app/src/main/java/org/astraea/argument/BooleanField.java b/app/src/main/java/org/astraea/app/argument/BooleanField.java
similarity index 92%
rename from app/src/main/java/org/astraea/argument/BooleanField.java
rename to app/src/main/java/org/astraea/app/argument/BooleanField.java
index 51ea1b82..6f4b2b97 100644
--- a/app/src/main/java/org/astraea/argument/BooleanField.java
+++ b/app/src/main/java/org/astraea/app/argument/BooleanField.java
@@ -1,4 +1,4 @@
-package org.astraea.argument;
+package org.astraea.app.argument;
 
 import com.beust.jcommander.ParameterException;
 
diff --git a/app/src/main/java/org/astraea/argument/CompressionField.java b/app/src/main/java/org/astraea/app/argument/CompressionField.java
similarity index 92%
rename from app/src/main/java/org/astraea/argument/CompressionField.java
rename to app/src/main/java/org/astraea/app/argument/CompressionField.java
index 996ea6c4..fa459b06 100644
--- a/app/src/main/java/org/astraea/argument/CompressionField.java
+++ b/app/src/main/java/org/astraea/app/argument/CompressionField.java
@@ -1,10 +1,10 @@
-package org.astraea.argument;
+package org.astraea.app.argument;
 
 import com.beust.jcommander.ParameterException;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 import org.apache.kafka.common.record.CompressionType;
-import org.astraea.admin.Compression;
+import org.astraea.app.admin.Compression;
 
 public class CompressionField extends Field<Compression> {
   /**
diff --git a/app/src/main/java/org/astraea/argument/DurationField.java b/app/src/main/java/org/astraea/app/argument/DurationField.java
similarity index 98%
rename from app/src/main/java/org/astraea/argument/DurationField.java
rename to app/src/main/java/org/astraea/app/argument/DurationField.java
index f42303d8..33709a7b 100644
--- a/app/src/main/java/org/astraea/argument/DurationField.java
+++ b/app/src/main/java/org/astraea/app/argument/DurationField.java
@@ -1,4 +1,4 @@
-package org.astraea.argument;
+package org.astraea.app.argument;
 
 import com.beust.jcommander.ParameterException;
 import java.time.Duration;
diff --git a/app/src/main/java/org/astraea/argument/Field.java b/app/src/main/java/org/astraea/app/argument/Field.java
similarity index 97%
rename from app/src/main/java/org/astraea/argument/Field.java
rename to app/src/main/java/org/astraea/app/argument/Field.java
index 15122d2f..d1f6eb78 100644
--- a/app/src/main/java/org/astraea/argument/Field.java
+++ b/app/src/main/java/org/astraea/app/argument/Field.java
@@ -1,4 +1,4 @@
-package org.astraea.argument;
+package org.astraea.app.argument;
 
 import com.beust.jcommander.IParameterValidator;
 import com.beust.jcommander.IStringConverter;
diff --git a/app/src/main/java/org/astraea/argument/IntegerSetField.java b/app/src/main/java/org/astraea/app/argument/IntegerSetField.java
similarity index 90%
rename from app/src/main/java/org/astraea/argument/IntegerSetField.java
rename to app/src/main/java/org/astraea/app/argument/IntegerSetField.java
index 7ed2e703..59d8f8b3 100644
--- a/app/src/main/java/org/astraea/argument/IntegerSetField.java
+++ b/app/src/main/java/org/astraea/app/argument/IntegerSetField.java
@@ -1,4 +1,4 @@
-package org.astraea.argument;
+package org.astraea.app.argument;
 
 import java.util.Set;
 import java.util.stream.Collectors;
diff --git a/app/src/main/java/org/astraea/argument/NonEmptyStringField.java b/app/src/main/java/org/astraea/app/argument/NonEmptyStringField.java
similarity index 79%
rename from app/src/main/java/org/astraea/argument/NonEmptyStringField.java
rename to app/src/main/java/org/astraea/app/argument/NonEmptyStringField.java
index 3edafd10..416b41aa 100644
--- a/app/src/main/java/org/astraea/argument/NonEmptyStringField.java
+++ b/app/src/main/java/org/astraea/app/argument/NonEmptyStringField.java
@@ -1,4 +1,4 @@
-package org.astraea.argument;
+package org.astraea.app.argument;
 
 public class NonEmptyStringField extends Field<String> {
   @Override
diff --git a/app/src/main/java/org/astraea/argument/NonNegativeDoubleField.java b/app/src/main/java/org/astraea/app/argument/NonNegativeDoubleField.java
similarity index 83%
rename from app/src/main/java/org/astraea/argument/NonNegativeDoubleField.java
rename to app/src/main/java/org/astraea/app/argument/NonNegativeDoubleField.java
index 44617641..7a6e1f0e 100644
--- a/app/src/main/java/org/astraea/argument/NonNegativeDoubleField.java
+++ b/app/src/main/java/org/astraea/app/argument/NonNegativeDoubleField.java
@@ -1,4 +1,4 @@
-package org.astraea.argument;
+package org.astraea.app.argument;
 
 public class NonNegativeDoubleField extends NonNegativeNumberField<Double> {
   @Override
diff --git a/app/src/main/java/org/astraea/argument/NonNegativeIntegerField.java b/app/src/main/java/org/astraea/app/argument/NonNegativeIntegerField.java
similarity index 83%
rename from app/src/main/java/org/astraea/argument/NonNegativeIntegerField.java
rename to app/src/main/java/org/astraea/app/argument/NonNegativeIntegerField.java
index 05c6ac6d..c4846a84 100644
--- a/app/src/main/java/org/astraea/argument/NonNegativeIntegerField.java
+++ b/app/src/main/java/org/astraea/app/argument/NonNegativeIntegerField.java
@@ -1,4 +1,4 @@
-package org.astraea.argument;
+package org.astraea.app.argument;
 
 public class NonNegativeIntegerField extends NonNegativeNumberField<Integer> {
   @Override
diff --git a/app/src/main/java/org/astraea/argument/NonNegativeLongField.java b/app/src/main/java/org/astraea/app/argument/NonNegativeLongField.java
similarity index 82%
rename from app/src/main/java/org/astraea/argument/NonNegativeLongField.java
rename to app/src/main/java/org/astraea/app/argument/NonNegativeLongField.java
index 1baaf119..2d7eb724 100644
--- a/app/src/main/java/org/astraea/argument/NonNegativeLongField.java
+++ b/app/src/main/java/org/astraea/app/argument/NonNegativeLongField.java
@@ -1,4 +1,4 @@
-package org.astraea.argument;
+package org.astraea.app.argument;
 
 public class NonNegativeLongField extends NonNegativeNumberField<Long> {
   @Override
diff --git a/app/src/main/java/org/astraea/argument/NonNegativeNumberField.java b/app/src/main/java/org/astraea/app/argument/NonNegativeNumberField.java
similarity index 90%
rename from app/src/main/java/org/astraea/argument/NonNegativeNumberField.java
rename to app/src/main/java/org/astraea/app/argument/NonNegativeNumberField.java
index dc9e0a6d..9416e944 100644
--- a/app/src/main/java/org/astraea/argument/NonNegativeNumberField.java
+++ b/app/src/main/java/org/astraea/app/argument/NonNegativeNumberField.java
@@ -1,4 +1,4 @@
-package org.astraea.argument;
+package org.astraea.app.argument;
 
 import com.beust.jcommander.ParameterException;
 
diff --git a/app/src/main/java/org/astraea/argument/NonNegativeShortField.java b/app/src/main/java/org/astraea/app/argument/NonNegativeShortField.java
similarity index 83%
rename from app/src/main/java/org/astraea/argument/NonNegativeShortField.java
rename to app/src/main/java/org/astraea/app/argument/NonNegativeShortField.java
index a8032303..e40390b0 100644
--- a/app/src/main/java/org/astraea/argument/NonNegativeShortField.java
+++ b/app/src/main/java/org/astraea/app/argument/NonNegativeShortField.java
@@ -1,4 +1,4 @@
-package org.astraea.argument;
+package org.astraea.app.argument;
 
 public class NonNegativeShortField extends NonNegativeNumberField<Short> {
   @Override
diff --git a/app/src/main/java/org/astraea/argument/PathField.java b/app/src/main/java/org/astraea/app/argument/PathField.java
similarity index 86%
rename from app/src/main/java/org/astraea/argument/PathField.java
rename to app/src/main/java/org/astraea/app/argument/PathField.java
index 1cced1e6..b61c431a 100644
--- a/app/src/main/java/org/astraea/argument/PathField.java
+++ b/app/src/main/java/org/astraea/app/argument/PathField.java
@@ -1,4 +1,4 @@
-package org.astraea.argument;
+package org.astraea.app.argument;
 
 import java.nio.file.FileSystems;
 import java.nio.file.Path;
diff --git a/app/src/main/java/org/astraea/argument/PositiveDoubleField.java b/app/src/main/java/org/astraea/app/argument/PositiveDoubleField.java
similarity index 83%
rename from app/src/main/java/org/astraea/argument/PositiveDoubleField.java
rename to app/src/main/java/org/astraea/app/argument/PositiveDoubleField.java
index b06c2686..cedb3524 100644
--- a/app/src/main/java/org/astraea/argument/PositiveDoubleField.java
+++ b/app/src/main/java/org/astraea/app/argument/PositiveDoubleField.java
@@ -1,4 +1,4 @@
-package org.astraea.argument;
+package org.astraea.app.argument;
 
 public class PositiveDoubleField extends PositiveNumberField<Double> {
   @Override
diff --git a/app/src/main/java/org/astraea/argument/PositiveIntegerField.java b/app/src/main/java/org/astraea/app/argument/PositiveIntegerField.java
similarity index 83%
rename from app/src/main/java/org/astraea/argument/PositiveIntegerField.java
rename to app/src/main/java/org/astraea/app/argument/PositiveIntegerField.java
index 8d4ed69e..0439f279 100644
--- a/app/src/main/java/org/astraea/argument/PositiveIntegerField.java
+++ b/app/src/main/java/org/astraea/app/argument/PositiveIntegerField.java
@@ -1,4 +1,4 @@
-package org.astraea.argument;
+package org.astraea.app.argument;
 
 public class PositiveIntegerField extends PositiveNumberField<Integer> {
   @Override
diff --git a/app/src/main/java/org/astraea/argument/PositiveLongField.java b/app/src/main/java/org/astraea/app/argument/PositiveLongField.java
similarity index 82%
rename from app/src/main/java/org/astraea/argument/PositiveLongField.java
rename to app/src/main/java/org/astraea/app/argument/PositiveLongField.java
index 58aa3c40..815ce3c1 100644
--- a/app/src/main/java/org/astraea/argument/PositiveLongField.java
+++ b/app/src/main/java/org/astraea/app/argument/PositiveLongField.java
@@ -1,4 +1,4 @@
-package org.astraea.argument;
+package org.astraea.app.argument;
 
 public class PositiveLongField extends PositiveNumberField<Long> {
   @Override
diff --git a/app/src/main/java/org/astraea/argument/PositiveNumberField.java b/app/src/main/java/org/astraea/app/argument/PositiveNumberField.java
similarity index 90%
rename from app/src/main/java/org/astraea/argument/PositiveNumberField.java
rename to app/src/main/java/org/astraea/app/argument/PositiveNumberField.java
index 636f2307..fb362aa8 100644
--- a/app/src/main/java/org/astraea/argument/PositiveNumberField.java
+++ b/app/src/main/java/org/astraea/app/argument/PositiveNumberField.java
@@ -1,4 +1,4 @@
-package org.astraea.argument;
+package org.astraea.app.argument;
 
 import com.beust.jcommander.ParameterException;
 
diff --git a/app/src/main/java/org/astraea/argument/PositiveShortField.java b/app/src/main/java/org/astraea/app/argument/PositiveShortField.java
similarity index 82%
rename from app/src/main/java/org/astraea/argument/PositiveShortField.java
rename to app/src/main/java/org/astraea/app/argument/PositiveShortField.java
index 32ace72c..aac985a0 100644
--- a/app/src/main/java/org/astraea/argument/PositiveShortField.java
+++ b/app/src/main/java/org/astraea/app/argument/PositiveShortField.java
@@ -1,4 +1,4 @@
-package org.astraea.argument;
+package org.astraea.app.argument;
 
 public class PositiveShortField extends PositiveNumberField<Short> {
   @Override
diff --git a/app/src/main/java/org/astraea/argument/SetField.java b/app/src/main/java/org/astraea/app/argument/SetField.java
similarity index 92%
rename from app/src/main/java/org/astraea/argument/SetField.java
rename to app/src/main/java/org/astraea/app/argument/SetField.java
index 387df36a..624d19f0 100644
--- a/app/src/main/java/org/astraea/argument/SetField.java
+++ b/app/src/main/java/org/astraea/app/argument/SetField.java
@@ -1,4 +1,4 @@
-package org.astraea.argument;
+package org.astraea.app.argument;
 
 import com.beust.jcommander.ParameterException;
 import java.util.Set;
diff --git a/app/src/main/java/org/astraea/argument/StringMapField.java b/app/src/main/java/org/astraea/app/argument/StringMapField.java
similarity index 96%
rename from app/src/main/java/org/astraea/argument/StringMapField.java
rename to app/src/main/java/org/astraea/app/argument/StringMapField.java
index e54b3d08..e1963fee 100644
--- a/app/src/main/java/org/astraea/argument/StringMapField.java
+++ b/app/src/main/java/org/astraea/app/argument/StringMapField.java
@@ -1,4 +1,4 @@
-package org.astraea.argument;
+package org.astraea.app.argument;
 
 import com.beust.jcommander.ParameterException;
 import java.util.Arrays;
diff --git a/app/src/main/java/org/astraea/argument/StringSetField.java b/app/src/main/java/org/astraea/app/argument/StringSetField.java
similarity index 84%
rename from app/src/main/java/org/astraea/argument/StringSetField.java
rename to app/src/main/java/org/astraea/app/argument/StringSetField.java
index bb264ff0..1ba79d48 100644
--- a/app/src/main/java/org/astraea/argument/StringSetField.java
+++ b/app/src/main/java/org/astraea/app/argument/StringSetField.java
@@ -1,4 +1,4 @@
-package org.astraea.argument;
+package org.astraea.app.argument;
 
 import java.util.Set;
 
diff --git a/app/src/main/java/org/astraea/automation/Automation.java b/app/src/main/java/org/astraea/app/automation/Automation.java
similarity index 91%
rename from app/src/main/java/org/astraea/automation/Automation.java
rename to app/src/main/java/org/astraea/app/automation/Automation.java
index 7486c675..7e68ec9b 100644
--- a/app/src/main/java/org/astraea/automation/Automation.java
+++ b/app/src/main/java/org/astraea/app/automation/Automation.java
@@ -1,4 +1,4 @@
-package org.astraea.automation;
+package org.astraea.app.automation;
 
 import com.beust.jcommander.Parameter;
 import java.io.FileInputStream;
@@ -10,8 +10,8 @@ import java.util.concurrent.ExecutionException;
 import org.apache.kafka.clients.admin.AdminClient;
 import org.apache.kafka.clients.admin.AdminClientConfig;
 import org.apache.kafka.clients.admin.KafkaAdminClient;
-import org.astraea.argument.NonEmptyStringField;
-import org.astraea.performance.Performance;
+import org.astraea.app.argument.NonEmptyStringField;
+import org.astraea.app.performance.Performance;
 
 /**
  * By configuring the parameters in config/automation.properties, control the execution times of
@@ -41,7 +41,7 @@ public class Automation {
   public static void main(String[] args) {
     try {
       var properties = new Properties();
-      var arg = org.astraea.argument.Argument.parse(new Argument(), args);
+      var arg = org.astraea.app.argument.Argument.parse(new Argument(), args);
       properties.load(new FileInputStream(arg.address));
       var whetherDeleteTopic = properties.getProperty("--whetherDeleteTopic").equals("true");
       var bootstrap = properties.getProperty("--bootstrap.servers");
@@ -56,7 +56,7 @@ public class Automation {
       while (i < times) {
         var result =
             Performance.execute(
-                org.astraea.argument.Argument.parse(
+                org.astraea.app.argument.Argument.parse(
                     new Performance.Argument(), performanceArgs(properties)));
         i++;
         if (whetherDeleteTopic) {
diff --git a/app/src/main/java/org/astraea/balancer/RebalancePlanProposal.java b/app/src/main/java/org/astraea/app/balancer/RebalancePlanProposal.java
similarity index 97%
rename from app/src/main/java/org/astraea/balancer/RebalancePlanProposal.java
rename to app/src/main/java/org/astraea/app/balancer/RebalancePlanProposal.java
index a411a16a..acf432d1 100644
--- a/app/src/main/java/org/astraea/balancer/RebalancePlanProposal.java
+++ b/app/src/main/java/org/astraea/app/balancer/RebalancePlanProposal.java
@@ -1,11 +1,11 @@
-package org.astraea.balancer;
+package org.astraea.app.balancer;
 
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.Objects;
 import java.util.Optional;
-import org.astraea.balancer.log.ClusterLogAllocation;
+import org.astraea.app.balancer.log.ClusterLogAllocation;
 
 public interface RebalancePlanProposal {
 
diff --git a/app/src/main/java/org/astraea/balancer/generator/RebalancePlanGenerator.java b/app/src/main/java/org/astraea/app/balancer/generator/RebalancePlanGenerator.java
similarity index 84%
rename from app/src/main/java/org/astraea/balancer/generator/RebalancePlanGenerator.java
rename to app/src/main/java/org/astraea/app/balancer/generator/RebalancePlanGenerator.java
index 40dfa1e4..f8c2191b 100644
--- a/app/src/main/java/org/astraea/balancer/generator/RebalancePlanGenerator.java
+++ b/app/src/main/java/org/astraea/app/balancer/generator/RebalancePlanGenerator.java
@@ -1,10 +1,10 @@
-package org.astraea.balancer.generator;
+package org.astraea.app.balancer.generator;
 
 import java.util.stream.Stream;
-import org.astraea.balancer.RebalancePlanProposal;
-import org.astraea.balancer.log.ClusterLogAllocation;
-import org.astraea.balancer.log.LayeredClusterLogAllocation;
-import org.astraea.cost.ClusterInfo;
+import org.astraea.app.balancer.RebalancePlanProposal;
+import org.astraea.app.balancer.log.ClusterLogAllocation;
+import org.astraea.app.balancer.log.LayeredClusterLogAllocation;
+import org.astraea.app.cost.ClusterInfo;
 
 /** */
 public interface RebalancePlanGenerator {
diff --git a/app/src/main/java/org/astraea/balancer/generator/ShufflePlanGenerator.java b/app/src/main/java/org/astraea/app/balancer/generator/ShufflePlanGenerator.java
similarity index 96%
rename from app/src/main/java/org/astraea/balancer/generator/ShufflePlanGenerator.java
rename to app/src/main/java/org/astraea/app/balancer/generator/ShufflePlanGenerator.java
index d1c55bb8..88d6c328 100644
--- a/app/src/main/java/org/astraea/balancer/generator/ShufflePlanGenerator.java
+++ b/app/src/main/java/org/astraea/app/balancer/generator/ShufflePlanGenerator.java
@@ -1,4 +1,4 @@
-package org.astraea.balancer.generator;
+package org.astraea.app.balancer.generator;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -9,13 +9,13 @@ import java.util.function.Supplier;
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
 import java.util.stream.Stream;
-import org.astraea.admin.TopicPartition;
-import org.astraea.balancer.RebalancePlanProposal;
-import org.astraea.balancer.log.ClusterLogAllocation;
-import org.astraea.balancer.log.LayeredClusterLogAllocation;
-import org.astraea.balancer.log.LogPlacement;
-import org.astraea.cost.ClusterInfo;
-import org.astraea.cost.NodeInfo;
+import org.astraea.app.admin.TopicPartition;
+import org.astraea.app.balancer.RebalancePlanProposal;
+import org.astraea.app.balancer.log.ClusterLogAllocation;
+import org.astraea.app.balancer.log.LayeredClusterLogAllocation;
+import org.astraea.app.balancer.log.LogPlacement;
+import org.astraea.app.cost.ClusterInfo;
+import org.astraea.app.cost.NodeInfo;
 
 /**
  * The {@link ShufflePlanGenerator} proposes a new log placement based on the current log placement,
diff --git a/app/src/main/java/org/astraea/balancer/log/ClusterLogAllocation.java b/app/src/main/java/org/astraea/app/balancer/log/ClusterLogAllocation.java
similarity index 93%
rename from app/src/main/java/org/astraea/balancer/log/ClusterLogAllocation.java
rename to app/src/main/java/org/astraea/app/balancer/log/ClusterLogAllocation.java
index a0fe097b..7bd80d7e 100644
--- a/app/src/main/java/org/astraea/balancer/log/ClusterLogAllocation.java
+++ b/app/src/main/java/org/astraea/app/balancer/log/ClusterLogAllocation.java
@@ -1,8 +1,8 @@
-package org.astraea.balancer.log;
+package org.astraea.app.balancer.log;
 
 import java.util.List;
 import java.util.stream.Stream;
-import org.astraea.admin.TopicPartition;
+import org.astraea.app.admin.TopicPartition;
 
 /**
  * Describe the log allocation state of a Kafka cluster. The implementation have to keep the cluster
diff --git a/app/src/main/java/org/astraea/balancer/log/IllegalMigrationException.java b/app/src/main/java/org/astraea/app/balancer/log/IllegalMigrationException.java
similarity index 77%
rename from app/src/main/java/org/astraea/balancer/log/IllegalMigrationException.java
rename to app/src/main/java/org/astraea/app/balancer/log/IllegalMigrationException.java
index bf3f26e8..0c566823 100644
--- a/app/src/main/java/org/astraea/balancer/log/IllegalMigrationException.java
+++ b/app/src/main/java/org/astraea/app/balancer/log/IllegalMigrationException.java
@@ -1,4 +1,4 @@
-package org.astraea.balancer.log;
+package org.astraea.app.balancer.log;
 
 public class IllegalMigrationException extends RuntimeException {
   public IllegalMigrationException(String s) {
diff --git a/app/src/main/java/org/astraea/balancer/log/LayeredClusterLogAllocation.java b/app/src/main/java/org/astraea/app/balancer/log/LayeredClusterLogAllocation.java
similarity index 98%
rename from app/src/main/java/org/astraea/balancer/log/LayeredClusterLogAllocation.java
rename to app/src/main/java/org/astraea/app/balancer/log/LayeredClusterLogAllocation.java
index 56f838da..1d599d2e 100644
--- a/app/src/main/java/org/astraea/balancer/log/LayeredClusterLogAllocation.java
+++ b/app/src/main/java/org/astraea/app/balancer/log/LayeredClusterLogAllocation.java
@@ -1,4 +1,4 @@
-package org.astraea.balancer.log;
+package org.astraea.app.balancer.log;
 
 import java.util.Collection;
 import java.util.Comparator;
@@ -10,9 +10,9 @@ import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
 import java.util.stream.Stream;
-import org.astraea.admin.TopicPartition;
-import org.astraea.cost.ClusterInfo;
-import org.astraea.cost.ReplicaInfo;
+import org.astraea.app.admin.TopicPartition;
+import org.astraea.app.cost.ClusterInfo;
+import org.astraea.app.cost.ReplicaInfo;
 
 public class LayeredClusterLogAllocation implements ClusterLogAllocation {
 
diff --git a/app/src/main/java/org/astraea/balancer/log/LogPlacement.java b/app/src/main/java/org/astraea/app/balancer/log/LogPlacement.java
similarity index 96%
rename from app/src/main/java/org/astraea/balancer/log/LogPlacement.java
rename to app/src/main/java/org/astraea/app/balancer/log/LogPlacement.java
index 2f75a23b..f0a1e9a2 100644
--- a/app/src/main/java/org/astraea/balancer/log/LogPlacement.java
+++ b/app/src/main/java/org/astraea/app/balancer/log/LogPlacement.java
@@ -1,4 +1,4 @@
-package org.astraea.balancer.log;
+package org.astraea.app.balancer.log;
 
 import java.util.Optional;
 
diff --git a/app/src/main/java/org/astraea/common/DataRate.java b/app/src/main/java/org/astraea/app/common/DataRate.java
similarity index 99%
rename from app/src/main/java/org/astraea/common/DataRate.java
rename to app/src/main/java/org/astraea/app/common/DataRate.java
index 40f1e686..ac3b16bd 100644
--- a/app/src/main/java/org/astraea/common/DataRate.java
+++ b/app/src/main/java/org/astraea/app/common/DataRate.java
@@ -1,4 +1,4 @@
-package org.astraea.common;
+package org.astraea.app.common;
 
 import java.math.BigDecimal;
 import java.math.BigInteger;
diff --git a/app/src/main/java/org/astraea/common/DataSize.java b/app/src/main/java/org/astraea/app/common/DataSize.java
similarity index 98%
rename from app/src/main/java/org/astraea/common/DataSize.java
rename to app/src/main/java/org/astraea/app/common/DataSize.java
index f0165df9..a1b51126 100644
--- a/app/src/main/java/org/astraea/common/DataSize.java
+++ b/app/src/main/java/org/astraea/app/common/DataSize.java
@@ -1,4 +1,4 @@
-package org.astraea.common;
+package org.astraea.app.common;
 
 import java.math.BigDecimal;
 import java.math.BigInteger;
@@ -214,7 +214,7 @@ public class DataSize implements Comparable<DataSize> {
     return Objects.hash(bits);
   }
 
-  public static class Field extends org.astraea.argument.Field<DataSize> {
+  public static class Field extends org.astraea.app.argument.Field<DataSize> {
     // Parse number and DataUnit
     private static final Pattern DATA_SIZE_PATTERN =
         Pattern.compile("(?<measurement>[0-9]+)\\s?(?<dataUnit>[a-zA-Z]+)");
diff --git a/app/src/main/java/org/astraea/common/DataUnit.java b/app/src/main/java/org/astraea/app/common/DataUnit.java
similarity index 98%
rename from app/src/main/java/org/astraea/common/DataUnit.java
rename to app/src/main/java/org/astraea/app/common/DataUnit.java
index a197d0ae..1526730d 100644
--- a/app/src/main/java/org/astraea/common/DataUnit.java
+++ b/app/src/main/java/org/astraea/app/common/DataUnit.java
@@ -1,4 +1,4 @@
-package org.astraea.common;
+package org.astraea.app.common;
 
 import java.math.BigInteger;
 import java.util.Arrays;
diff --git a/app/src/main/java/org/astraea/common/Utils.java b/app/src/main/java/org/astraea/app/common/Utils.java
similarity index 99%
rename from app/src/main/java/org/astraea/common/Utils.java
rename to app/src/main/java/org/astraea/app/common/Utils.java
index 328a75ce..969fbec6 100644
--- a/app/src/main/java/org/astraea/common/Utils.java
+++ b/app/src/main/java/org/astraea/app/common/Utils.java
@@ -1,4 +1,4 @@
-package org.astraea.common;
+package org.astraea.app.common;
 
 import java.io.File;
 import java.net.InetAddress;
diff --git a/app/src/main/java/org/astraea/concurrent/Executor.java b/app/src/main/java/org/astraea/app/concurrent/Executor.java
similarity index 93%
rename from app/src/main/java/org/astraea/concurrent/Executor.java
rename to app/src/main/java/org/astraea/app/concurrent/Executor.java
index 624b21c4..dbc224fc 100644
--- a/app/src/main/java/org/astraea/concurrent/Executor.java
+++ b/app/src/main/java/org/astraea/app/concurrent/Executor.java
@@ -1,4 +1,4 @@
-package org.astraea.concurrent;
+package org.astraea.app.concurrent;
 
 @FunctionalInterface
 public interface Executor extends AutoCloseable {
diff --git a/app/src/main/java/org/astraea/concurrent/State.java b/app/src/main/java/org/astraea/app/concurrent/State.java
similarity index 80%
rename from app/src/main/java/org/astraea/concurrent/State.java
rename to app/src/main/java/org/astraea/app/concurrent/State.java
index 1a55800f..2b571680 100644
--- a/app/src/main/java/org/astraea/concurrent/State.java
+++ b/app/src/main/java/org/astraea/app/concurrent/State.java
@@ -1,4 +1,4 @@
-package org.astraea.concurrent;
+package org.astraea.app.concurrent;
 
 public enum State {
   /** this thread is done. ThreadPool will call close to release the thread. */
diff --git a/app/src/main/java/org/astraea/concurrent/ThreadPool.java b/app/src/main/java/org/astraea/app/concurrent/ThreadPool.java
similarity index 98%
rename from app/src/main/java/org/astraea/concurrent/ThreadPool.java
rename to app/src/main/java/org/astraea/app/concurrent/ThreadPool.java
index 4db9ef26..c85cadd5 100644
--- a/app/src/main/java/org/astraea/concurrent/ThreadPool.java
+++ b/app/src/main/java/org/astraea/app/concurrent/ThreadPool.java
@@ -1,4 +1,4 @@
-package org.astraea.concurrent;
+package org.astraea.app.concurrent;
 
 import java.util.ArrayList;
 import java.util.Collection;
diff --git a/app/src/main/java/org/astraea/consumer/Builder.java b/app/src/main/java/org/astraea/app/consumer/Builder.java
similarity index 99%
rename from app/src/main/java/org/astraea/consumer/Builder.java
rename to app/src/main/java/org/astraea/app/consumer/Builder.java
index cb17c699..625e4c14 100644
--- a/app/src/main/java/org/astraea/consumer/Builder.java
+++ b/app/src/main/java/org/astraea/app/consumer/Builder.java
@@ -1,4 +1,4 @@
-package org.astraea.consumer;
+package org.astraea.app.consumer;
 
 import java.time.Duration;
 import java.util.ArrayList;
diff --git a/app/src/main/java/org/astraea/consumer/Consumer.java b/app/src/main/java/org/astraea/app/consumer/Consumer.java
similarity index 97%
rename from app/src/main/java/org/astraea/consumer/Consumer.java
rename to app/src/main/java/org/astraea/app/consumer/Consumer.java
index 1848ed22..967f298b 100644
--- a/app/src/main/java/org/astraea/consumer/Consumer.java
+++ b/app/src/main/java/org/astraea/app/consumer/Consumer.java
@@ -1,4 +1,4 @@
-package org.astraea.consumer;
+package org.astraea.app.consumer;
 
 import java.time.Duration;
 import java.util.Collection;
diff --git a/app/src/main/java/org/astraea/consumer/ConsumerRebalanceListener.java b/app/src/main/java/org/astraea/app/consumer/ConsumerRebalanceListener.java
similarity index 93%
rename from app/src/main/java/org/astraea/consumer/ConsumerRebalanceListener.java
rename to app/src/main/java/org/astraea/app/consumer/ConsumerRebalanceListener.java
index 00dd5139..4fdc5217 100644
--- a/app/src/main/java/org/astraea/consumer/ConsumerRebalanceListener.java
+++ b/app/src/main/java/org/astraea/app/consumer/ConsumerRebalanceListener.java
@@ -1,9 +1,9 @@
-package org.astraea.consumer;
+package org.astraea.app.consumer;
 
 import java.util.Collection;
 import java.util.Set;
 import java.util.stream.Collectors;
-import org.astraea.admin.TopicPartition;
+import org.astraea.app.admin.TopicPartition;
 
 @FunctionalInterface
 public interface ConsumerRebalanceListener {
diff --git a/app/src/main/java/org/astraea/consumer/Deserializer.java b/app/src/main/java/org/astraea/app/consumer/Deserializer.java
similarity index 98%
rename from app/src/main/java/org/astraea/consumer/Deserializer.java
rename to app/src/main/java/org/astraea/app/consumer/Deserializer.java
index 147dabe4..92e89920 100644
--- a/app/src/main/java/org/astraea/consumer/Deserializer.java
+++ b/app/src/main/java/org/astraea/app/consumer/Deserializer.java
@@ -1,4 +1,4 @@
-package org.astraea.consumer;
+package org.astraea.app.consumer;
 
 import java.util.Collection;
 import java.util.List;
diff --git a/app/src/main/java/org/astraea/consumer/Header.java b/app/src/main/java/org/astraea/app/consumer/Header.java
similarity index 97%
rename from app/src/main/java/org/astraea/consumer/Header.java
rename to app/src/main/java/org/astraea/app/consumer/Header.java
index 20d9c38b..e3008b4c 100644
--- a/app/src/main/java/org/astraea/consumer/Header.java
+++ b/app/src/main/java/org/astraea/app/consumer/Header.java
@@ -1,4 +1,4 @@
-package org.astraea.consumer;
+package org.astraea.app.consumer;
 
 import java.util.Collection;
 import java.util.stream.Collectors;
diff --git a/app/src/main/java/org/astraea/consumer/Isolation.java b/app/src/main/java/org/astraea/app/consumer/Isolation.java
similarity index 90%
rename from app/src/main/java/org/astraea/consumer/Isolation.java
rename to app/src/main/java/org/astraea/app/consumer/Isolation.java
index 63b91501..71763674 100644
--- a/app/src/main/java/org/astraea/consumer/Isolation.java
+++ b/app/src/main/java/org/astraea/app/consumer/Isolation.java
@@ -1,4 +1,4 @@
-package org.astraea.consumer;
+package org.astraea.app.consumer;
 
 import java.util.Locale;
 
diff --git a/app/src/main/java/org/astraea/consumer/Record.java b/app/src/main/java/org/astraea/app/consumer/Record.java
similarity index 98%
rename from app/src/main/java/org/astraea/consumer/Record.java
rename to app/src/main/java/org/astraea/app/consumer/Record.java
index e6b0070c..d73f6ac3 100644
--- a/app/src/main/java/org/astraea/consumer/Record.java
+++ b/app/src/main/java/org/astraea/app/consumer/Record.java
@@ -1,4 +1,4 @@
-package org.astraea.consumer;
+package org.astraea.app.consumer;
 
 import java.util.Collection;
 import java.util.Collections;
diff --git a/app/src/main/java/org/astraea/cost/BrokerCost.java b/app/src/main/java/org/astraea/app/cost/BrokerCost.java
similarity index 87%
rename from app/src/main/java/org/astraea/cost/BrokerCost.java
rename to app/src/main/java/org/astraea/app/cost/BrokerCost.java
index da4b145b..4b5dd2a7 100644
--- a/app/src/main/java/org/astraea/cost/BrokerCost.java
+++ b/app/src/main/java/org/astraea/app/cost/BrokerCost.java
@@ -1,4 +1,4 @@
-package org.astraea.cost;
+package org.astraea.app.cost;
 
 import java.util.Map;
 
diff --git a/app/src/main/java/org/astraea/cost/ClusterInfo.java b/app/src/main/java/org/astraea/app/cost/ClusterInfo.java
similarity index 98%
rename from app/src/main/java/org/astraea/cost/ClusterInfo.java
rename to app/src/main/java/org/astraea/app/cost/ClusterInfo.java
index 408c459b..eb26b94c 100644
--- a/app/src/main/java/org/astraea/cost/ClusterInfo.java
+++ b/app/src/main/java/org/astraea/app/cost/ClusterInfo.java
@@ -1,4 +1,4 @@
-package org.astraea.cost;
+package org.astraea.app.cost;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -9,7 +9,7 @@ import java.util.Map;
 import java.util.NoSuchElementException;
 import java.util.Set;
 import java.util.stream.Collectors;
-import org.astraea.metrics.HasBeanObject;
+import org.astraea.app.metrics.HasBeanObject;
 
 public interface ClusterInfo {
 
diff --git a/app/src/main/java/org/astraea/cost/CostFunction.java b/app/src/main/java/org/astraea/app/cost/CostFunction.java
similarity index 82%
rename from app/src/main/java/org/astraea/cost/CostFunction.java
rename to app/src/main/java/org/astraea/app/cost/CostFunction.java
index 61db0f9a..2f75d8f5 100644
--- a/app/src/main/java/org/astraea/cost/CostFunction.java
+++ b/app/src/main/java/org/astraea/app/cost/CostFunction.java
@@ -1,6 +1,6 @@
-package org.astraea.cost;
+package org.astraea.app.cost;
 
-import org.astraea.metrics.collector.Fetcher;
+import org.astraea.app.metrics.collector.Fetcher;
 
 /**
  * It is meaningless to implement this interface. Instead, we should implement interfaces like
diff --git a/app/src/main/java/org/astraea/cost/HasBrokerCost.java b/app/src/main/java/org/astraea/app/cost/HasBrokerCost.java
similarity index 91%
rename from app/src/main/java/org/astraea/cost/HasBrokerCost.java
rename to app/src/main/java/org/astraea/app/cost/HasBrokerCost.java
index 6da60d10..fad62c85 100644
--- a/app/src/main/java/org/astraea/cost/HasBrokerCost.java
+++ b/app/src/main/java/org/astraea/app/cost/HasBrokerCost.java
@@ -1,4 +1,4 @@
-package org.astraea.cost;
+package org.astraea.app.cost;
 
 public interface HasBrokerCost extends CostFunction {
   /**
diff --git a/app/src/main/java/org/astraea/cost/HasPartitionCost.java b/app/src/main/java/org/astraea/app/cost/HasPartitionCost.java
similarity index 91%
rename from app/src/main/java/org/astraea/cost/HasPartitionCost.java
rename to app/src/main/java/org/astraea/app/cost/HasPartitionCost.java
index 66e6556d..eb675322 100644
--- a/app/src/main/java/org/astraea/cost/HasPartitionCost.java
+++ b/app/src/main/java/org/astraea/app/cost/HasPartitionCost.java
@@ -1,4 +1,4 @@
-package org.astraea.cost;
+package org.astraea.app.cost;
 
 public interface HasPartitionCost extends CostFunction {
   /**
diff --git a/app/src/main/java/org/astraea/cost/LoadCost.java b/app/src/main/java/org/astraea/app/cost/LoadCost.java
similarity index 96%
rename from app/src/main/java/org/astraea/cost/LoadCost.java
rename to app/src/main/java/org/astraea/app/cost/LoadCost.java
index 0313fce3..6295f8ef 100644
--- a/app/src/main/java/org/astraea/cost/LoadCost.java
+++ b/app/src/main/java/org/astraea/app/cost/LoadCost.java
@@ -1,4 +1,4 @@
-package org.astraea.cost;
+package org.astraea.app.cost;
 
 import java.util.Collection;
 import java.util.HashMap;
@@ -6,11 +6,11 @@ import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
-import org.astraea.metrics.HasBeanObject;
-import org.astraea.metrics.collector.Fetcher;
-import org.astraea.metrics.kafka.BrokerTopicMetricsResult;
-import org.astraea.metrics.kafka.KafkaMetrics;
-import org.astraea.partitioner.PartitionerUtils;
+import org.astraea.app.metrics.HasBeanObject;
+import org.astraea.app.metrics.collector.Fetcher;
+import org.astraea.app.metrics.kafka.BrokerTopicMetricsResult;
+import org.astraea.app.metrics.kafka.KafkaMetrics;
+import org.astraea.app.partitioner.PartitionerUtils;
 
 public class LoadCost implements HasBrokerCost {
   private final Map<Integer, BrokerMetric> brokersMetric = new HashMap<>();
diff --git a/app/src/main/java/org/astraea/cost/NodeInfo.java b/app/src/main/java/org/astraea/app/cost/NodeInfo.java
similarity index 97%
rename from app/src/main/java/org/astraea/cost/NodeInfo.java
rename to app/src/main/java/org/astraea/app/cost/NodeInfo.java
index f7633d4a..d19d312f 100644
--- a/app/src/main/java/org/astraea/cost/NodeInfo.java
+++ b/app/src/main/java/org/astraea/app/cost/NodeInfo.java
@@ -1,4 +1,4 @@
-package org.astraea.cost;
+package org.astraea.app.cost;
 
 import java.util.Objects;
 
diff --git a/app/src/main/java/org/astraea/cost/Normalizer.java b/app/src/main/java/org/astraea/app/cost/Normalizer.java
similarity index 98%
rename from app/src/main/java/org/astraea/cost/Normalizer.java
rename to app/src/main/java/org/astraea/app/cost/Normalizer.java
index 8dba2999..703967fc 100644
--- a/app/src/main/java/org/astraea/cost/Normalizer.java
+++ b/app/src/main/java/org/astraea/app/cost/Normalizer.java
@@ -1,4 +1,4 @@
-package org.astraea.cost;
+package org.astraea.app.cost;
 
 import java.util.Collection;
 import java.util.Comparator;
diff --git a/app/src/main/java/org/astraea/cost/PartitionCost.java b/app/src/main/java/org/astraea/app/cost/PartitionCost.java
similarity index 90%
rename from app/src/main/java/org/astraea/cost/PartitionCost.java
rename to app/src/main/java/org/astraea/app/cost/PartitionCost.java
index 4628f650..2a11a1aa 100644
--- a/app/src/main/java/org/astraea/cost/PartitionCost.java
+++ b/app/src/main/java/org/astraea/app/cost/PartitionCost.java
@@ -1,7 +1,7 @@
-package org.astraea.cost;
+package org.astraea.app.cost;
 
 import java.util.Map;
-import org.astraea.admin.TopicPartition;
+import org.astraea.app.admin.TopicPartition;
 
 /** Return type of cost function, `HasPartitionCost`. It returns the score of partitions. */
 public interface PartitionCost {
diff --git a/app/src/main/java/org/astraea/cost/Periodic.java b/app/src/main/java/org/astraea/app/cost/Periodic.java
similarity index 94%
rename from app/src/main/java/org/astraea/cost/Periodic.java
rename to app/src/main/java/org/astraea/app/cost/Periodic.java
index 3ddf331b..88798547 100644
--- a/app/src/main/java/org/astraea/cost/Periodic.java
+++ b/app/src/main/java/org/astraea/app/cost/Periodic.java
@@ -1,8 +1,8 @@
-package org.astraea.cost;
+package org.astraea.app.cost;
 
 import java.time.Duration;
 import java.util.function.Supplier;
-import org.astraea.common.Utils;
+import org.astraea.app.common.Utils;
 
 /** Enables methods to be updated periodically, not calculated every time they are called. */
 public abstract class Periodic<Value> {
diff --git a/app/src/main/java/org/astraea/cost/ReplicaInfo.java b/app/src/main/java/org/astraea/app/cost/ReplicaInfo.java
similarity index 99%
rename from app/src/main/java/org/astraea/cost/ReplicaInfo.java
rename to app/src/main/java/org/astraea/app/cost/ReplicaInfo.java
index 13bb677b..a7b88bf6 100644
--- a/app/src/main/java/org/astraea/cost/ReplicaInfo.java
+++ b/app/src/main/java/org/astraea/app/cost/ReplicaInfo.java
@@ -1,4 +1,4 @@
-package org.astraea.cost;
+package org.astraea.app.cost;
 
 import java.util.List;
 import java.util.Optional;
diff --git a/app/src/main/java/org/astraea/cost/ThroughputCost.java b/app/src/main/java/org/astraea/app/cost/ThroughputCost.java
similarity index 85%
rename from app/src/main/java/org/astraea/cost/ThroughputCost.java
rename to app/src/main/java/org/astraea/app/cost/ThroughputCost.java
index 73c3950f..0183256b 100644
--- a/app/src/main/java/org/astraea/cost/ThroughputCost.java
+++ b/app/src/main/java/org/astraea/app/cost/ThroughputCost.java
@@ -1,13 +1,13 @@
-package org.astraea.cost;
+package org.astraea.app.cost;
 
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
-import org.astraea.metrics.HasBeanObject;
-import org.astraea.metrics.collector.Fetcher;
-import org.astraea.metrics.kafka.BrokerTopicMetricsResult;
-import org.astraea.metrics.kafka.KafkaMetrics;
+import org.astraea.app.metrics.HasBeanObject;
+import org.astraea.app.metrics.collector.Fetcher;
+import org.astraea.app.metrics.kafka.BrokerTopicMetricsResult;
+import org.astraea.app.metrics.kafka.KafkaMetrics;
 
 public class ThroughputCost implements HasBrokerCost {
 
diff --git a/app/src/main/java/org/astraea/cost/WeightProvider.java b/app/src/main/java/org/astraea/app/cost/WeightProvider.java
similarity index 98%
rename from app/src/main/java/org/astraea/cost/WeightProvider.java
rename to app/src/main/java/org/astraea/app/cost/WeightProvider.java
index 0cb9b66e..25f86835 100644
--- a/app/src/main/java/org/astraea/cost/WeightProvider.java
+++ b/app/src/main/java/org/astraea/app/cost/WeightProvider.java
@@ -1,4 +1,4 @@
-package org.astraea.cost;
+package org.astraea.app.cost;
 
 import java.util.Collection;
 import java.util.Map;
diff --git a/app/src/main/java/org/astraea/cost/broker/BrokerInputCost.java b/app/src/main/java/org/astraea/app/cost/broker/BrokerInputCost.java
similarity index 88%
rename from app/src/main/java/org/astraea/cost/broker/BrokerInputCost.java
rename to app/src/main/java/org/astraea/app/cost/broker/BrokerInputCost.java
index 721a8ad2..3f760c5c 100644
--- a/app/src/main/java/org/astraea/cost/broker/BrokerInputCost.java
+++ b/app/src/main/java/org/astraea/app/cost/broker/BrokerInputCost.java
@@ -1,18 +1,16 @@
-package org.astraea.cost.broker;
-
-import static org.astraea.cost.broker.CostUtils.TScore;
+package org.astraea.app.cost.broker;
 
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
-import org.astraea.cost.BrokerCost;
-import org.astraea.cost.ClusterInfo;
-import org.astraea.cost.HasBrokerCost;
-import org.astraea.metrics.collector.Fetcher;
-import org.astraea.metrics.kafka.BrokerTopicMetricsResult;
-import org.astraea.metrics.kafka.KafkaMetrics;
+import org.astraea.app.cost.BrokerCost;
+import org.astraea.app.cost.ClusterInfo;
+import org.astraea.app.cost.HasBrokerCost;
+import org.astraea.app.metrics.collector.Fetcher;
+import org.astraea.app.metrics.kafka.BrokerTopicMetricsResult;
+import org.astraea.app.metrics.kafka.KafkaMetrics;
 
 /**
  * The result is computed by "BytesInPerSec.count". "BytesInPerSec.count" responds to the input
@@ -60,7 +58,7 @@ public class BrokerInputCost implements HasBrokerCost {
                       return count;
                     }));
 
-    TScore(costMetrics).forEach((broker, v) -> brokersMetric.get(broker).updateLoad(v));
+    CostUtils.TScore(costMetrics).forEach((broker, v) -> brokersMetric.get(broker).updateLoad(v));
 
     return this::computeLoad;
   }
diff --git a/app/src/main/java/org/astraea/cost/broker/BrokerOutputCost.java b/app/src/main/java/org/astraea/app/cost/broker/BrokerOutputCost.java
similarity index 88%
rename from app/src/main/java/org/astraea/cost/broker/BrokerOutputCost.java
rename to app/src/main/java/org/astraea/app/cost/broker/BrokerOutputCost.java
index 58bc6888..c156d071 100644
--- a/app/src/main/java/org/astraea/cost/broker/BrokerOutputCost.java
+++ b/app/src/main/java/org/astraea/app/cost/broker/BrokerOutputCost.java
@@ -1,18 +1,16 @@
-package org.astraea.cost.broker;
-
-import static org.astraea.cost.broker.CostUtils.TScore;
+package org.astraea.app.cost.broker;
 
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
-import org.astraea.cost.BrokerCost;
-import org.astraea.cost.ClusterInfo;
-import org.astraea.cost.HasBrokerCost;
-import org.astraea.metrics.collector.Fetcher;
-import org.astraea.metrics.kafka.BrokerTopicMetricsResult;
-import org.astraea.metrics.kafka.KafkaMetrics;
+import org.astraea.app.cost.BrokerCost;
+import org.astraea.app.cost.ClusterInfo;
+import org.astraea.app.cost.HasBrokerCost;
+import org.astraea.app.metrics.collector.Fetcher;
+import org.astraea.app.metrics.kafka.BrokerTopicMetricsResult;
+import org.astraea.app.metrics.kafka.KafkaMetrics;
 
 /**
  * The result is computed by "BytesOutPerSec.count". "BytesOutPerSec.count" responds to the output
@@ -60,7 +58,7 @@ public class BrokerOutputCost implements HasBrokerCost {
                       return count;
                     }));
 
-    TScore(costMetrics).forEach((broker, v) -> brokersMetric.get(broker).updateLoad(v));
+    CostUtils.TScore(costMetrics).forEach((broker, v) -> brokersMetric.get(broker).updateLoad(v));
 
     return this::computeLoad;
   }
diff --git a/app/src/main/java/org/astraea/cost/broker/CostUtils.java b/app/src/main/java/org/astraea/app/cost/broker/CostUtils.java
similarity index 98%
rename from app/src/main/java/org/astraea/cost/broker/CostUtils.java
rename to app/src/main/java/org/astraea/app/cost/broker/CostUtils.java
index 8706204a..6ee53df6 100644
--- a/app/src/main/java/org/astraea/cost/broker/CostUtils.java
+++ b/app/src/main/java/org/astraea/app/cost/broker/CostUtils.java
@@ -1,4 +1,4 @@
-package org.astraea.cost.broker;
+package org.astraea.app.cost.broker;
 
 import java.util.Map;
 import java.util.concurrent.atomic.AtomicReference;
diff --git a/app/src/main/java/org/astraea/cost/broker/CpuCost.java b/app/src/main/java/org/astraea/app/cost/broker/CpuCost.java
similarity index 87%
rename from app/src/main/java/org/astraea/cost/broker/CpuCost.java
rename to app/src/main/java/org/astraea/app/cost/broker/CpuCost.java
index fa45fe8e..dfbb025e 100644
--- a/app/src/main/java/org/astraea/cost/broker/CpuCost.java
+++ b/app/src/main/java/org/astraea/app/cost/broker/CpuCost.java
@@ -1,18 +1,16 @@
-package org.astraea.cost.broker;
-
-import static org.astraea.cost.broker.CostUtils.TScore;
+package org.astraea.app.cost.broker;
 
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
-import org.astraea.cost.BrokerCost;
-import org.astraea.cost.ClusterInfo;
-import org.astraea.cost.HasBrokerCost;
-import org.astraea.metrics.collector.Fetcher;
-import org.astraea.metrics.java.OperatingSystemInfo;
-import org.astraea.metrics.kafka.KafkaMetrics;
+import org.astraea.app.cost.BrokerCost;
+import org.astraea.app.cost.ClusterInfo;
+import org.astraea.app.cost.HasBrokerCost;
+import org.astraea.app.metrics.collector.Fetcher;
+import org.astraea.app.metrics.java.OperatingSystemInfo;
+import org.astraea.app.metrics.kafka.KafkaMetrics;
 
 /**
  * The result is computed by "OperatingSystemInfo.systemCpuLoad".
@@ -53,7 +51,7 @@ public class CpuCost implements HasBrokerCost {
                       return cpuBean.systemCpuLoad();
                     }));
 
-    TScore(costMetrics).forEach((broker, v) -> brokersMetric.get(broker).updateLoad(v));
+    CostUtils.TScore(costMetrics).forEach((broker, v) -> brokersMetric.get(broker).updateLoad(v));
 
     return this::computeLoad;
   }
diff --git a/app/src/main/java/org/astraea/cost/broker/MemoryCost.java b/app/src/main/java/org/astraea/app/cost/broker/MemoryCost.java
similarity index 87%
rename from app/src/main/java/org/astraea/cost/broker/MemoryCost.java
rename to app/src/main/java/org/astraea/app/cost/broker/MemoryCost.java
index 91b05219..a454a98d 100644
--- a/app/src/main/java/org/astraea/cost/broker/MemoryCost.java
+++ b/app/src/main/java/org/astraea/app/cost/broker/MemoryCost.java
@@ -1,19 +1,17 @@
-package org.astraea.cost.broker;
-
-import static org.astraea.cost.broker.CostUtils.TScore;
+package org.astraea.app.cost.broker;
 
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
-import org.astraea.cost.BrokerCost;
-import org.astraea.cost.ClusterInfo;
-import org.astraea.cost.HasBrokerCost;
-import org.astraea.cost.Periodic;
-import org.astraea.metrics.collector.Fetcher;
-import org.astraea.metrics.java.HasJvmMemory;
-import org.astraea.metrics.kafka.KafkaMetrics;
+import org.astraea.app.cost.BrokerCost;
+import org.astraea.app.cost.ClusterInfo;
+import org.astraea.app.cost.HasBrokerCost;
+import org.astraea.app.cost.Periodic;
+import org.astraea.app.metrics.collector.Fetcher;
+import org.astraea.app.metrics.java.HasJvmMemory;
+import org.astraea.app.metrics.kafka.KafkaMetrics;
 
 public class MemoryCost extends Periodic<Map<Integer, Double>> implements HasBrokerCost {
   private final Map<Integer, BrokerMetric> brokersMetric = new HashMap<>();
@@ -55,7 +53,7 @@ public class MemoryCost extends Periodic<Map<Integer, Double>> implements HasBro
                           / (jvmBean.heapMemoryUsage().getMax() + 1);
                     }));
 
-    TScore(costMetrics).forEach((broker, v) -> brokersMetric.get(broker).updateLoad(v));
+    CostUtils.TScore(costMetrics).forEach((broker, v) -> brokersMetric.get(broker).updateLoad(v));
 
     return this::computeLoad;
   }
diff --git a/app/src/main/java/org/astraea/cost/broker/NeutralIntegratedCost.java b/app/src/main/java/org/astraea/app/cost/broker/NeutralIntegratedCost.java
similarity index 95%
rename from app/src/main/java/org/astraea/cost/broker/NeutralIntegratedCost.java
rename to app/src/main/java/org/astraea/app/cost/broker/NeutralIntegratedCost.java
index 50316d21..32ab406f 100644
--- a/app/src/main/java/org/astraea/cost/broker/NeutralIntegratedCost.java
+++ b/app/src/main/java/org/astraea/app/cost/broker/NeutralIntegratedCost.java
@@ -1,17 +1,17 @@
-package org.astraea.cost.broker;
+package org.astraea.app.cost.broker;
 
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
-import org.astraea.cost.BrokerCost;
-import org.astraea.cost.ClusterInfo;
-import org.astraea.cost.CostFunction;
-import org.astraea.cost.HasBrokerCost;
-import org.astraea.cost.Normalizer;
-import org.astraea.cost.WeightProvider;
-import org.astraea.metrics.collector.Fetcher;
+import org.astraea.app.cost.BrokerCost;
+import org.astraea.app.cost.ClusterInfo;
+import org.astraea.app.cost.CostFunction;
+import org.astraea.app.cost.HasBrokerCost;
+import org.astraea.app.cost.Normalizer;
+import org.astraea.app.cost.WeightProvider;
+import org.astraea.app.metrics.collector.Fetcher;
 
 /**
  * The result is computed by four cost function.There are "BrokerInputCost", "BrokerOutputCost",
diff --git a/app/src/main/java/org/astraea/cost/topic/CalculateUtils.java b/app/src/main/java/org/astraea/app/cost/topic/CalculateUtils.java
similarity index 98%
rename from app/src/main/java/org/astraea/cost/topic/CalculateUtils.java
rename to app/src/main/java/org/astraea/app/cost/topic/CalculateUtils.java
index 0117adec..de67a6a2 100644
--- a/app/src/main/java/org/astraea/cost/topic/CalculateUtils.java
+++ b/app/src/main/java/org/astraea/app/cost/topic/CalculateUtils.java
@@ -1,4 +1,4 @@
-package org.astraea.cost.topic;
+package org.astraea.app.cost.topic;
 
 import java.util.HashMap;
 import java.util.HashSet;
@@ -7,7 +7,7 @@ import java.util.Set;
 import java.util.TreeMap;
 import java.util.function.Function;
 import java.util.stream.Collectors;
-import org.astraea.admin.TopicPartition;
+import org.astraea.app.admin.TopicPartition;
 
 public class CalculateUtils {
   public static Map<Integer, Map<TopicPartition, Double>> getLoad(
diff --git a/app/src/main/java/org/astraea/cost/topic/GetPartitionInf.java b/app/src/main/java/org/astraea/app/cost/topic/GetPartitionInf.java
similarity index 93%
rename from app/src/main/java/org/astraea/cost/topic/GetPartitionInf.java
rename to app/src/main/java/org/astraea/app/cost/topic/GetPartitionInf.java
index ce100283..72eb914a 100644
--- a/app/src/main/java/org/astraea/cost/topic/GetPartitionInf.java
+++ b/app/src/main/java/org/astraea/app/cost/topic/GetPartitionInf.java
@@ -1,12 +1,12 @@
-package org.astraea.cost.topic;
+package org.astraea.app.cost.topic;
 
 import java.util.HashMap;
 import java.util.Map;
 import java.util.NoSuchElementException;
 import java.util.TreeMap;
 import java.util.stream.Collectors;
-import org.astraea.admin.Admin;
-import org.astraea.admin.TopicPartition;
+import org.astraea.app.admin.Admin;
+import org.astraea.app.admin.TopicPartition;
 
 public class GetPartitionInf {
   static Map<Integer, Map<TopicPartition, Integer>> getSize(Admin client) {
diff --git a/app/src/main/java/org/astraea/cost/topic/PartitionScore.java b/app/src/main/java/org/astraea/app/cost/topic/PartitionScore.java
similarity index 91%
rename from app/src/main/java/org/astraea/cost/topic/PartitionScore.java
rename to app/src/main/java/org/astraea/app/cost/topic/PartitionScore.java
index 45a54711..b940c79e 100644
--- a/app/src/main/java/org/astraea/cost/topic/PartitionScore.java
+++ b/app/src/main/java/org/astraea/app/cost/topic/PartitionScore.java
@@ -1,4 +1,4 @@
-package org.astraea.cost.topic;
+package org.astraea.app.cost.topic;
 
 import com.beust.jcommander.Parameter;
 import java.util.ArrayList;
@@ -7,9 +7,9 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.stream.Collectors;
-import org.astraea.admin.Admin;
-import org.astraea.admin.TopicPartition;
-import org.astraea.argument.BooleanField;
+import org.astraea.app.admin.Admin;
+import org.astraea.app.admin.TopicPartition;
+import org.astraea.app.argument.BooleanField;
 
 public class PartitionScore {
   public static void printScore(
@@ -77,13 +77,13 @@ public class PartitionScore {
   }
 
   public static void main(String[] args) {
-    var argument = org.astraea.argument.Argument.parse(new Argument(), args);
+    var argument = org.astraea.app.argument.Argument.parse(new Argument(), args);
     var admin = Admin.of(argument.bootstrapServers());
     var score = execute(argument, admin);
     printScore(score, argument);
   }
 
-  static class Argument extends org.astraea.argument.Argument {
+  static class Argument extends org.astraea.app.argument.Argument {
     @Parameter(
         names = {"--exclude.internal.topics"},
         description =
diff --git a/app/src/main/java/org/astraea/database/Builder.java b/app/src/main/java/org/astraea/app/database/Builder.java
similarity index 99%
rename from app/src/main/java/org/astraea/database/Builder.java
rename to app/src/main/java/org/astraea/app/database/Builder.java
index b7ead224..f9138872 100644
--- a/app/src/main/java/org/astraea/database/Builder.java
+++ b/app/src/main/java/org/astraea/app/database/Builder.java
@@ -1,4 +1,4 @@
-package org.astraea.database;
+package org.astraea.app.database;
 
 import java.sql.Connection;
 import java.sql.DriverManager;
@@ -16,7 +16,7 @@ import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
 import java.util.stream.Collectors;
-import org.astraea.common.Utils;
+import org.astraea.app.common.Utils;
 
 public class Builder {
   private String url;
diff --git a/app/src/main/java/org/astraea/database/ColumnInfo.java b/app/src/main/java/org/astraea/app/database/ColumnInfo.java
similarity index 96%
rename from app/src/main/java/org/astraea/database/ColumnInfo.java
rename to app/src/main/java/org/astraea/app/database/ColumnInfo.java
index efd5ad9c..c1dc187a 100644
--- a/app/src/main/java/org/astraea/database/ColumnInfo.java
+++ b/app/src/main/java/org/astraea/app/database/ColumnInfo.java
@@ -1,4 +1,4 @@
-package org.astraea.database;
+package org.astraea.app.database;
 
 import java.util.Objects;
 
diff --git a/app/src/main/java/org/astraea/database/DatabaseClient.java b/app/src/main/java/org/astraea/app/database/DatabaseClient.java
similarity index 92%
rename from app/src/main/java/org/astraea/database/DatabaseClient.java
rename to app/src/main/java/org/astraea/app/database/DatabaseClient.java
index 2db85383..dd2916c3 100644
--- a/app/src/main/java/org/astraea/database/DatabaseClient.java
+++ b/app/src/main/java/org/astraea/app/database/DatabaseClient.java
@@ -1,4 +1,4 @@
-package org.astraea.database;
+package org.astraea.app.database;
 
 public interface DatabaseClient extends AutoCloseable {
 
diff --git a/app/src/main/java/org/astraea/database/TableCreator.java b/app/src/main/java/org/astraea/app/database/TableCreator.java
similarity index 93%
rename from app/src/main/java/org/astraea/database/TableCreator.java
rename to app/src/main/java/org/astraea/app/database/TableCreator.java
index 7758ef47..e05cc982 100644
--- a/app/src/main/java/org/astraea/database/TableCreator.java
+++ b/app/src/main/java/org/astraea/app/database/TableCreator.java
@@ -1,4 +1,4 @@
-package org.astraea.database;
+package org.astraea.app.database;
 
 public interface TableCreator {
 
diff --git a/app/src/main/java/org/astraea/database/TableInfo.java b/app/src/main/java/org/astraea/app/database/TableInfo.java
similarity index 96%
rename from app/src/main/java/org/astraea/database/TableInfo.java
rename to app/src/main/java/org/astraea/app/database/TableInfo.java
index 7c382c48..d72aaba0 100644
--- a/app/src/main/java/org/astraea/database/TableInfo.java
+++ b/app/src/main/java/org/astraea/app/database/TableInfo.java
@@ -1,4 +1,4 @@
-package org.astraea.database;
+package org.astraea.app.database;
 
 import java.util.Collection;
 import java.util.Objects;
diff --git a/app/src/main/java/org/astraea/database/TableQuery.java b/app/src/main/java/org/astraea/app/database/TableQuery.java
similarity index 94%
rename from app/src/main/java/org/astraea/database/TableQuery.java
rename to app/src/main/java/org/astraea/app/database/TableQuery.java
index 9d88cb73..82332fbb 100644
--- a/app/src/main/java/org/astraea/database/TableQuery.java
+++ b/app/src/main/java/org/astraea/app/database/TableQuery.java
@@ -1,4 +1,4 @@
-package org.astraea.database;
+package org.astraea.app.database;
 
 import java.util.Collection;
 
diff --git a/app/src/main/java/org/astraea/metrics/HasBeanObject.java b/app/src/main/java/org/astraea/app/metrics/HasBeanObject.java
similarity index 65%
rename from app/src/main/java/org/astraea/metrics/HasBeanObject.java
rename to app/src/main/java/org/astraea/app/metrics/HasBeanObject.java
index 52252068..3a18b3e6 100644
--- a/app/src/main/java/org/astraea/metrics/HasBeanObject.java
+++ b/app/src/main/java/org/astraea/app/metrics/HasBeanObject.java
@@ -1,6 +1,6 @@
-package org.astraea.metrics;
+package org.astraea.app.metrics;
 
-import org.astraea.metrics.jmx.BeanObject;
+import org.astraea.app.metrics.jmx.BeanObject;
 
 public interface HasBeanObject {
   BeanObject beanObject();
diff --git a/app/src/main/java/org/astraea/metrics/MetricExplorer.java b/app/src/main/java/org/astraea/app/metrics/MetricExplorer.java
similarity index 97%
rename from app/src/main/java/org/astraea/metrics/MetricExplorer.java
rename to app/src/main/java/org/astraea/app/metrics/MetricExplorer.java
index 437ecd56..d84071d3 100644
--- a/app/src/main/java/org/astraea/metrics/MetricExplorer.java
+++ b/app/src/main/java/org/astraea/app/metrics/MetricExplorer.java
@@ -1,4 +1,4 @@
-package org.astraea.metrics;
+package org.astraea.app.metrics;
 
 import com.beust.jcommander.IParameterValidator;
 import com.beust.jcommander.Parameter;
@@ -16,9 +16,10 @@ import java.util.stream.IntStream;
 import java.util.stream.Stream;
 import javax.management.openmbean.CompositeDataSupport;
 import javax.management.remote.JMXServiceURL;
-import org.astraea.metrics.jmx.BeanObject;
-import org.astraea.metrics.jmx.BeanQuery;
-import org.astraea.metrics.jmx.MBeanClient;
+import org.astraea.app.argument.Field;
+import org.astraea.app.metrics.jmx.BeanObject;
+import org.astraea.app.metrics.jmx.BeanQuery;
+import org.astraea.app.metrics.jmx.MBeanClient;
 
 public class MetricExplorer {
 
@@ -165,7 +166,7 @@ public class MetricExplorer {
   }
 
   public static void main(String[] args) {
-    var arguments = org.astraea.argument.Argument.parse(new Argument(), args);
+    var arguments = org.astraea.app.argument.Argument.parse(new Argument(), args);
 
     try (var mBeanClient = MBeanClient.of(arguments.jmxServer)) {
       execute(mBeanClient, arguments);
@@ -205,7 +206,7 @@ public class MetricExplorer {
         description = "Show the list view of MBeans' domain name & properties")
     boolean viewObjectNameList = false;
 
-    public static class JmxServerUrlField extends org.astraea.argument.Field<JMXServiceURL> {
+    public static class JmxServerUrlField extends Field<JMXServiceURL> {
 
       /** This regex used to test if a string look like a JMX URL */
       static Pattern patternOfJmxUrlStart = Pattern.compile("^service:jmx:rmi://");
diff --git a/app/src/main/java/org/astraea/metrics/collector/BeanCollector.java b/app/src/main/java/org/astraea/app/metrics/collector/BeanCollector.java
similarity index 96%
rename from app/src/main/java/org/astraea/metrics/collector/BeanCollector.java
rename to app/src/main/java/org/astraea/app/metrics/collector/BeanCollector.java
index 1976a96f..bf14bb85 100644
--- a/app/src/main/java/org/astraea/metrics/collector/BeanCollector.java
+++ b/app/src/main/java/org/astraea/app/metrics/collector/BeanCollector.java
@@ -1,4 +1,4 @@
-package org.astraea.metrics.collector;
+package org.astraea.app.metrics.collector;
 
 import java.time.Duration;
 import java.util.Collection;
@@ -13,10 +13,10 @@ import java.util.concurrent.ConcurrentSkipListMap;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
 import java.util.function.BiFunction;
-import org.astraea.common.Utils;
-import org.astraea.metrics.HasBeanObject;
-import org.astraea.metrics.jmx.MBeanClient;
-import org.astraea.metrics.kafka.KafkaMetrics;
+import org.astraea.app.common.Utils;
+import org.astraea.app.metrics.HasBeanObject;
+import org.astraea.app.metrics.jmx.MBeanClient;
+import org.astraea.app.metrics.kafka.KafkaMetrics;
 
 public class BeanCollector {
 
diff --git a/app/src/main/java/org/astraea/metrics/collector/Fetcher.java b/app/src/main/java/org/astraea/app/metrics/collector/Fetcher.java
similarity index 81%
rename from app/src/main/java/org/astraea/metrics/collector/Fetcher.java
rename to app/src/main/java/org/astraea/app/metrics/collector/Fetcher.java
index 9e1b3677..dcc2cb21 100644
--- a/app/src/main/java/org/astraea/metrics/collector/Fetcher.java
+++ b/app/src/main/java/org/astraea/app/metrics/collector/Fetcher.java
@@ -1,9 +1,9 @@
-package org.astraea.metrics.collector;
+package org.astraea.app.metrics.collector;
 
 import java.util.Collection;
 import java.util.stream.Collectors;
-import org.astraea.metrics.HasBeanObject;
-import org.astraea.metrics.jmx.MBeanClient;
+import org.astraea.app.metrics.HasBeanObject;
+import org.astraea.app.metrics.jmx.MBeanClient;
 
 @FunctionalInterface
 public interface Fetcher {
diff --git a/app/src/main/java/org/astraea/metrics/collector/Receiver.java b/app/src/main/java/org/astraea/app/metrics/collector/Receiver.java
similarity index 85%
rename from app/src/main/java/org/astraea/metrics/collector/Receiver.java
rename to app/src/main/java/org/astraea/app/metrics/collector/Receiver.java
index 95e4eecc..4e8cec3e 100644
--- a/app/src/main/java/org/astraea/metrics/collector/Receiver.java
+++ b/app/src/main/java/org/astraea/app/metrics/collector/Receiver.java
@@ -1,7 +1,7 @@
-package org.astraea.metrics.collector;
+package org.astraea.app.metrics.collector;
 
 import java.util.Collection;
-import org.astraea.metrics.HasBeanObject;
+import org.astraea.app.metrics.HasBeanObject;
 
 /**
  * This Receiver is used to request mbeans. It must be closed. Otherwise, the true connection will
diff --git a/app/src/main/java/org/astraea/metrics/collector/Register.java b/app/src/main/java/org/astraea/app/metrics/collector/Register.java
similarity index 90%
rename from app/src/main/java/org/astraea/metrics/collector/Register.java
rename to app/src/main/java/org/astraea/app/metrics/collector/Register.java
index cce58c98..7482c956 100644
--- a/app/src/main/java/org/astraea/metrics/collector/Register.java
+++ b/app/src/main/java/org/astraea/app/metrics/collector/Register.java
@@ -1,4 +1,4 @@
-package org.astraea.metrics.collector;
+package org.astraea.app.metrics.collector;
 
 public interface Register {
 
diff --git a/app/src/main/java/org/astraea/metrics/java/HasJvmMemory.java b/app/src/main/java/org/astraea/app/metrics/java/HasJvmMemory.java
similarity index 84%
rename from app/src/main/java/org/astraea/metrics/java/HasJvmMemory.java
rename to app/src/main/java/org/astraea/app/metrics/java/HasJvmMemory.java
index b605fb3e..a209faf7 100644
--- a/app/src/main/java/org/astraea/metrics/java/HasJvmMemory.java
+++ b/app/src/main/java/org/astraea/app/metrics/java/HasJvmMemory.java
@@ -1,8 +1,8 @@
-package org.astraea.metrics.java;
+package org.astraea.app.metrics.java;
 
 import java.lang.management.MemoryUsage;
 import javax.management.openmbean.CompositeData;
-import org.astraea.metrics.HasBeanObject;
+import org.astraea.app.metrics.HasBeanObject;
 
 public interface HasJvmMemory extends HasBeanObject {
 
diff --git a/app/src/main/java/org/astraea/metrics/java/HasOperatingSystemInfo.java b/app/src/main/java/org/astraea/app/metrics/java/HasOperatingSystemInfo.java
similarity index 97%
rename from app/src/main/java/org/astraea/metrics/java/HasOperatingSystemInfo.java
rename to app/src/main/java/org/astraea/app/metrics/java/HasOperatingSystemInfo.java
index 19191a4d..903a4470 100644
--- a/app/src/main/java/org/astraea/metrics/java/HasOperatingSystemInfo.java
+++ b/app/src/main/java/org/astraea/app/metrics/java/HasOperatingSystemInfo.java
@@ -1,6 +1,6 @@
-package org.astraea.metrics.java;
+package org.astraea.app.metrics.java;
 
-import org.astraea.metrics.HasBeanObject;
+import org.astraea.app.metrics.HasBeanObject;
 
 public interface HasOperatingSystemInfo extends HasBeanObject {
 
diff --git a/app/src/main/java/org/astraea/metrics/java/JvmMemory.java b/app/src/main/java/org/astraea/app/metrics/java/JvmMemory.java
similarity index 93%
rename from app/src/main/java/org/astraea/metrics/java/JvmMemory.java
rename to app/src/main/java/org/astraea/app/metrics/java/JvmMemory.java
index 5c4d51ff..907a1222 100644
--- a/app/src/main/java/org/astraea/metrics/java/JvmMemory.java
+++ b/app/src/main/java/org/astraea/app/metrics/java/JvmMemory.java
@@ -1,7 +1,7 @@
-package org.astraea.metrics.java;
+package org.astraea.app.metrics.java;
 
 import java.lang.management.MemoryUsage;
-import org.astraea.metrics.jmx.BeanObject;
+import org.astraea.app.metrics.jmx.BeanObject;
 
 public class JvmMemory implements HasJvmMemory {
 
diff --git a/app/src/main/java/org/astraea/metrics/java/OperatingSystemInfo.java b/app/src/main/java/org/astraea/app/metrics/java/OperatingSystemInfo.java
similarity index 88%
rename from app/src/main/java/org/astraea/metrics/java/OperatingSystemInfo.java
rename to app/src/main/java/org/astraea/app/metrics/java/OperatingSystemInfo.java
index 3fa1d6bb..1d9cb538 100644
--- a/app/src/main/java/org/astraea/metrics/java/OperatingSystemInfo.java
+++ b/app/src/main/java/org/astraea/app/metrics/java/OperatingSystemInfo.java
@@ -1,7 +1,7 @@
-package org.astraea.metrics.java;
+package org.astraea.app.metrics.java;
 
 import java.util.Map;
-import org.astraea.metrics.jmx.BeanObject;
+import org.astraea.app.metrics.jmx.BeanObject;
 
 public class OperatingSystemInfo implements HasOperatingSystemInfo {
 
diff --git a/app/src/main/java/org/astraea/metrics/jmx/BeanObject.java b/app/src/main/java/org/astraea/app/metrics/jmx/BeanObject.java
similarity index 98%
rename from app/src/main/java/org/astraea/metrics/jmx/BeanObject.java
rename to app/src/main/java/org/astraea/app/metrics/jmx/BeanObject.java
index b1a6e509..74faafd5 100644
--- a/app/src/main/java/org/astraea/metrics/jmx/BeanObject.java
+++ b/app/src/main/java/org/astraea/app/metrics/jmx/BeanObject.java
@@ -1,4 +1,4 @@
-package org.astraea.metrics.jmx;
+package org.astraea.app.metrics.jmx;
 
 import static java.util.Map.Entry;
 
diff --git a/app/src/main/java/org/astraea/metrics/jmx/BeanQuery.java b/app/src/main/java/org/astraea/app/metrics/jmx/BeanQuery.java
similarity index 99%
rename from app/src/main/java/org/astraea/metrics/jmx/BeanQuery.java
rename to app/src/main/java/org/astraea/app/metrics/jmx/BeanQuery.java
index e9eeb162..5d715d34 100644
--- a/app/src/main/java/org/astraea/metrics/jmx/BeanQuery.java
+++ b/app/src/main/java/org/astraea/app/metrics/jmx/BeanQuery.java
@@ -1,4 +1,4 @@
-package org.astraea.metrics.jmx;
+package org.astraea.app.metrics.jmx;
 
 import java.util.HashMap;
 import java.util.Hashtable;
diff --git a/app/src/main/java/org/astraea/metrics/jmx/MBeanClient.java b/app/src/main/java/org/astraea/app/metrics/jmx/MBeanClient.java
similarity index 98%
rename from app/src/main/java/org/astraea/metrics/jmx/MBeanClient.java
rename to app/src/main/java/org/astraea/app/metrics/jmx/MBeanClient.java
index 91ad9654..b731403a 100644
--- a/app/src/main/java/org/astraea/metrics/jmx/MBeanClient.java
+++ b/app/src/main/java/org/astraea/app/metrics/jmx/MBeanClient.java
@@ -1,4 +1,4 @@
-package org.astraea.metrics.jmx;
+package org.astraea.app.metrics.jmx;
 
 import java.net.MalformedURLException;
 import java.util.Collection;
diff --git a/app/src/main/java/org/astraea/metrics/jmx/MBeanClientImpl.java b/app/src/main/java/org/astraea/app/metrics/jmx/MBeanClientImpl.java
similarity index 98%
rename from app/src/main/java/org/astraea/metrics/jmx/MBeanClientImpl.java
rename to app/src/main/java/org/astraea/app/metrics/jmx/MBeanClientImpl.java
index cf38e66e..413a632a 100644
--- a/app/src/main/java/org/astraea/metrics/jmx/MBeanClientImpl.java
+++ b/app/src/main/java/org/astraea/app/metrics/jmx/MBeanClientImpl.java
@@ -1,4 +1,4 @@
-package org.astraea.metrics.jmx;
+package org.astraea.app.metrics.jmx;
 
 import java.io.IOException;
 import java.io.UncheckedIOException;
@@ -22,7 +22,7 @@ import javax.management.ReflectionException;
 import javax.management.remote.JMXConnector;
 import javax.management.remote.JMXConnectorFactory;
 import javax.management.remote.JMXServiceURL;
-import org.astraea.common.Utils;
+import org.astraea.app.common.Utils;
 
 class MBeanClientImpl implements MBeanClient {
 
diff --git a/app/src/main/java/org/astraea/metrics/kafka/BrokerTopicMetricsResult.java b/app/src/main/java/org/astraea/app/metrics/kafka/BrokerTopicMetricsResult.java
similarity index 89%
rename from app/src/main/java/org/astraea/metrics/kafka/BrokerTopicMetricsResult.java
rename to app/src/main/java/org/astraea/app/metrics/kafka/BrokerTopicMetricsResult.java
index 36c6521a..d92059a6 100644
--- a/app/src/main/java/org/astraea/metrics/kafka/BrokerTopicMetricsResult.java
+++ b/app/src/main/java/org/astraea/app/metrics/kafka/BrokerTopicMetricsResult.java
@@ -1,8 +1,8 @@
-package org.astraea.metrics.kafka;
+package org.astraea.app.metrics.kafka;
 
 import java.util.Map;
 import java.util.Objects;
-import org.astraea.metrics.jmx.BeanObject;
+import org.astraea.app.metrics.jmx.BeanObject;
 
 public class BrokerTopicMetricsResult implements HasCount, HasEventType, HasRate {
 
diff --git a/app/src/main/java/org/astraea/metrics/kafka/HasCount.java b/app/src/main/java/org/astraea/app/metrics/kafka/HasCount.java
similarity index 64%
rename from app/src/main/java/org/astraea/metrics/kafka/HasCount.java
rename to app/src/main/java/org/astraea/app/metrics/kafka/HasCount.java
index 39633fa6..a619eee5 100644
--- a/app/src/main/java/org/astraea/metrics/kafka/HasCount.java
+++ b/app/src/main/java/org/astraea/app/metrics/kafka/HasCount.java
@@ -1,6 +1,6 @@
-package org.astraea.metrics.kafka;
+package org.astraea.app.metrics.kafka;
 
-import org.astraea.metrics.HasBeanObject;
+import org.astraea.app.metrics.HasBeanObject;
 
 public interface HasCount extends HasBeanObject {
   default long count() {
diff --git a/app/src/main/java/org/astraea/metrics/kafka/HasEventType.java b/app/src/main/java/org/astraea/app/metrics/kafka/HasEventType.java
similarity index 65%
rename from app/src/main/java/org/astraea/metrics/kafka/HasEventType.java
rename to app/src/main/java/org/astraea/app/metrics/kafka/HasEventType.java
index d74c9682..b8dc7327 100644
--- a/app/src/main/java/org/astraea/metrics/kafka/HasEventType.java
+++ b/app/src/main/java/org/astraea/app/metrics/kafka/HasEventType.java
@@ -1,6 +1,6 @@
-package org.astraea.metrics.kafka;
+package org.astraea.app.metrics.kafka;
 
-import org.astraea.metrics.HasBeanObject;
+import org.astraea.app.metrics.HasBeanObject;
 
 public interface HasEventType extends HasBeanObject {
   default String eventType() {
diff --git a/app/src/main/java/org/astraea/metrics/kafka/HasPercentiles.java b/app/src/main/java/org/astraea/app/metrics/kafka/HasPercentiles.java
similarity index 89%
rename from app/src/main/java/org/astraea/metrics/kafka/HasPercentiles.java
rename to app/src/main/java/org/astraea/app/metrics/kafka/HasPercentiles.java
index 7cd4087c..e80fce21 100644
--- a/app/src/main/java/org/astraea/metrics/kafka/HasPercentiles.java
+++ b/app/src/main/java/org/astraea/app/metrics/kafka/HasPercentiles.java
@@ -1,6 +1,6 @@
-package org.astraea.metrics.kafka;
+package org.astraea.app.metrics.kafka;
 
-import org.astraea.metrics.HasBeanObject;
+import org.astraea.app.metrics.HasBeanObject;
 
 public interface HasPercentiles extends HasBeanObject {
 
diff --git a/app/src/main/java/org/astraea/metrics/kafka/HasRate.java b/app/src/main/java/org/astraea/app/metrics/kafka/HasRate.java
similarity index 88%
rename from app/src/main/java/org/astraea/metrics/kafka/HasRate.java
rename to app/src/main/java/org/astraea/app/metrics/kafka/HasRate.java
index b4a68e2f..08197c35 100644
--- a/app/src/main/java/org/astraea/metrics/kafka/HasRate.java
+++ b/app/src/main/java/org/astraea/app/metrics/kafka/HasRate.java
@@ -1,7 +1,7 @@
-package org.astraea.metrics.kafka;
+package org.astraea.app.metrics.kafka;
 
 import java.util.concurrent.TimeUnit;
-import org.astraea.metrics.HasBeanObject;
+import org.astraea.app.metrics.HasBeanObject;
 
 public interface HasRate extends HasBeanObject {
   default double meanRate() {
diff --git a/app/src/main/java/org/astraea/metrics/kafka/HasStatistics.java b/app/src/main/java/org/astraea/app/metrics/kafka/HasStatistics.java
similarity index 83%
rename from app/src/main/java/org/astraea/metrics/kafka/HasStatistics.java
rename to app/src/main/java/org/astraea/app/metrics/kafka/HasStatistics.java
index 941b4098..bce44495 100644
--- a/app/src/main/java/org/astraea/metrics/kafka/HasStatistics.java
+++ b/app/src/main/java/org/astraea/app/metrics/kafka/HasStatistics.java
@@ -1,6 +1,6 @@
-package org.astraea.metrics.kafka;
+package org.astraea.app.metrics.kafka;
 
-import org.astraea.metrics.HasBeanObject;
+import org.astraea.app.metrics.HasBeanObject;
 
 public interface HasStatistics extends HasBeanObject {
 
diff --git a/app/src/main/java/org/astraea/metrics/kafka/HasValue.java b/app/src/main/java/org/astraea/app/metrics/kafka/HasValue.java
similarity index 67%
rename from app/src/main/java/org/astraea/metrics/kafka/HasValue.java
rename to app/src/main/java/org/astraea/app/metrics/kafka/HasValue.java
index 6f0203d4..c77cad9c 100644
--- a/app/src/main/java/org/astraea/metrics/kafka/HasValue.java
+++ b/app/src/main/java/org/astraea/app/metrics/kafka/HasValue.java
@@ -1,7 +1,7 @@
-package org.astraea.metrics.kafka;
+package org.astraea.app.metrics.kafka;
 
-import org.astraea.metrics.HasBeanObject;
-import org.astraea.metrics.jmx.BeanObject;
+import org.astraea.app.metrics.HasBeanObject;
+import org.astraea.app.metrics.jmx.BeanObject;
 
 public interface HasValue extends HasBeanObject {
   default long value() {
diff --git a/app/src/main/java/org/astraea/metrics/kafka/KafkaMetrics.java b/app/src/main/java/org/astraea/app/metrics/kafka/KafkaMetrics.java
similarity index 97%
rename from app/src/main/java/org/astraea/metrics/kafka/KafkaMetrics.java
rename to app/src/main/java/org/astraea/app/metrics/kafka/KafkaMetrics.java
index 74b36379..28b677ec 100644
--- a/app/src/main/java/org/astraea/metrics/kafka/KafkaMetrics.java
+++ b/app/src/main/java/org/astraea/app/metrics/kafka/KafkaMetrics.java
@@ -1,15 +1,15 @@
-package org.astraea.metrics.kafka;
+package org.astraea.app.metrics.kafka;
 
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Map;
 import java.util.stream.Collectors;
-import org.astraea.metrics.HasBeanObject;
-import org.astraea.metrics.java.JvmMemory;
-import org.astraea.metrics.java.OperatingSystemInfo;
-import org.astraea.metrics.jmx.BeanObject;
-import org.astraea.metrics.jmx.BeanQuery;
-import org.astraea.metrics.jmx.MBeanClient;
+import org.astraea.app.metrics.HasBeanObject;
+import org.astraea.app.metrics.java.JvmMemory;
+import org.astraea.app.metrics.java.OperatingSystemInfo;
+import org.astraea.app.metrics.jmx.BeanObject;
+import org.astraea.app.metrics.jmx.BeanQuery;
+import org.astraea.app.metrics.jmx.MBeanClient;
 
 public final class KafkaMetrics {
 
diff --git a/app/src/main/java/org/astraea/metrics/kafka/TotalTimeMs.java b/app/src/main/java/org/astraea/app/metrics/kafka/TotalTimeMs.java
similarity index 89%
rename from app/src/main/java/org/astraea/metrics/kafka/TotalTimeMs.java
rename to app/src/main/java/org/astraea/app/metrics/kafka/TotalTimeMs.java
index ca305344..4b0a6438 100644
--- a/app/src/main/java/org/astraea/metrics/kafka/TotalTimeMs.java
+++ b/app/src/main/java/org/astraea/app/metrics/kafka/TotalTimeMs.java
@@ -1,7 +1,7 @@
-package org.astraea.metrics.kafka;
+package org.astraea.app.metrics.kafka;
 
 import java.util.Map;
-import org.astraea.metrics.jmx.BeanObject;
+import org.astraea.app.metrics.jmx.BeanObject;
 
 public class TotalTimeMs implements HasPercentiles, HasCount, HasStatistics {
 
diff --git a/app/src/main/java/org/astraea/partitioner/Configuration.java b/app/src/main/java/org/astraea/app/partitioner/Configuration.java
similarity index 99%
rename from app/src/main/java/org/astraea/partitioner/Configuration.java
rename to app/src/main/java/org/astraea/app/partitioner/Configuration.java
index 00c44a03..419b8aa7 100644
--- a/app/src/main/java/org/astraea/partitioner/Configuration.java
+++ b/app/src/main/java/org/astraea/app/partitioner/Configuration.java
@@ -1,4 +1,4 @@
-package org.astraea.partitioner;
+package org.astraea.app.partitioner;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/app/src/main/java/org/astraea/partitioner/Dispatcher.java b/app/src/main/java/org/astraea/app/partitioner/Dispatcher.java
similarity index 94%
rename from app/src/main/java/org/astraea/partitioner/Dispatcher.java
rename to app/src/main/java/org/astraea/app/partitioner/Dispatcher.java
index 199b0a25..9f803a2c 100644
--- a/app/src/main/java/org/astraea/partitioner/Dispatcher.java
+++ b/app/src/main/java/org/astraea/app/partitioner/Dispatcher.java
@@ -1,10 +1,10 @@
-package org.astraea.partitioner;
+package org.astraea.app.partitioner;
 
 import java.util.Map;
 import java.util.stream.Collectors;
 import org.apache.kafka.clients.producer.Partitioner;
 import org.apache.kafka.common.Cluster;
-import org.astraea.cost.ClusterInfo;
+import org.astraea.app.cost.ClusterInfo;
 
 public interface Dispatcher extends Partitioner {
   /**
diff --git a/app/src/main/java/org/astraea/partitioner/PartitionerUtils.java b/app/src/main/java/org/astraea/app/partitioner/PartitionerUtils.java
similarity index 98%
rename from app/src/main/java/org/astraea/partitioner/PartitionerUtils.java
rename to app/src/main/java/org/astraea/app/partitioner/PartitionerUtils.java
index 48b1a051..4f5e2d17 100644
--- a/app/src/main/java/org/astraea/partitioner/PartitionerUtils.java
+++ b/app/src/main/java/org/astraea/app/partitioner/PartitionerUtils.java
@@ -1,4 +1,4 @@
-package org.astraea.partitioner;
+package org.astraea.app.partitioner;
 
 import java.io.FileInputStream;
 import java.io.IOException;
diff --git a/app/src/main/java/org/astraea/partitioner/StrictCostDispatcher.java b/app/src/main/java/org/astraea/app/partitioner/StrictCostDispatcher.java
similarity index 95%
rename from app/src/main/java/org/astraea/partitioner/StrictCostDispatcher.java
rename to app/src/main/java/org/astraea/app/partitioner/StrictCostDispatcher.java
index 9b6b6bc6..36b1f0b5 100644
--- a/app/src/main/java/org/astraea/partitioner/StrictCostDispatcher.java
+++ b/app/src/main/java/org/astraea/app/partitioner/StrictCostDispatcher.java
@@ -1,4 +1,4 @@
-package org.astraea.partitioner;
+package org.astraea.app.partitioner;
 
 import java.time.Duration;
 import java.util.Collection;
@@ -9,14 +9,14 @@ import java.util.Objects;
 import java.util.Optional;
 import java.util.TreeMap;
 import java.util.stream.Collectors;
-import org.astraea.common.Utils;
-import org.astraea.cost.ClusterInfo;
-import org.astraea.cost.CostFunction;
-import org.astraea.cost.HasBrokerCost;
-import org.astraea.cost.ReplicaInfo;
-import org.astraea.metrics.collector.BeanCollector;
-import org.astraea.metrics.collector.Fetcher;
-import org.astraea.metrics.collector.Receiver;
+import org.astraea.app.common.Utils;
+import org.astraea.app.cost.ClusterInfo;
+import org.astraea.app.cost.CostFunction;
+import org.astraea.app.cost.HasBrokerCost;
+import org.astraea.app.cost.ReplicaInfo;
+import org.astraea.app.metrics.collector.BeanCollector;
+import org.astraea.app.metrics.collector.Fetcher;
+import org.astraea.app.metrics.collector.Receiver;
 
 /**
  * this dispatcher scores the nodes by multiples cost functions. Each function evaluate the target
diff --git a/app/src/main/java/org/astraea/partitioner/smooth/SmoothWeightRoundRobin.java b/app/src/main/java/org/astraea/app/partitioner/smooth/SmoothWeightRoundRobin.java
similarity index 97%
rename from app/src/main/java/org/astraea/partitioner/smooth/SmoothWeightRoundRobin.java
rename to app/src/main/java/org/astraea/app/partitioner/smooth/SmoothWeightRoundRobin.java
index 32887eeb..9285619f 100644
--- a/app/src/main/java/org/astraea/partitioner/smooth/SmoothWeightRoundRobin.java
+++ b/app/src/main/java/org/astraea/app/partitioner/smooth/SmoothWeightRoundRobin.java
@@ -1,4 +1,4 @@
-package org.astraea.partitioner.smooth;
+package org.astraea.app.partitioner.smooth;
 
 import java.time.Duration;
 import java.util.Comparator;
@@ -6,9 +6,9 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
-import org.astraea.cost.ClusterInfo;
-import org.astraea.cost.Periodic;
-import org.astraea.cost.broker.CostUtils;
+import org.astraea.app.cost.ClusterInfo;
+import org.astraea.app.cost.Periodic;
+import org.astraea.app.cost.broker.CostUtils;
 
 /**
  * Given initial key-score pair, it will output a preferred key with the highest current weight. The
diff --git a/app/src/main/java/org/astraea/partitioner/smooth/SmoothWeightRoundRobinDispatcher.java b/app/src/main/java/org/astraea/app/partitioner/smooth/SmoothWeightRoundRobinDispatcher.java
similarity index 88%
rename from app/src/main/java/org/astraea/partitioner/smooth/SmoothWeightRoundRobinDispatcher.java
rename to app/src/main/java/org/astraea/app/partitioner/smooth/SmoothWeightRoundRobinDispatcher.java
index 318f9535..fbc0fdf3 100644
--- a/app/src/main/java/org/astraea/partitioner/smooth/SmoothWeightRoundRobinDispatcher.java
+++ b/app/src/main/java/org/astraea/app/partitioner/smooth/SmoothWeightRoundRobinDispatcher.java
@@ -1,6 +1,4 @@
-package org.astraea.partitioner.smooth;
-
-import static org.astraea.partitioner.PartitionerUtils.partitionerConfig;
+package org.astraea.app.partitioner.smooth;
 
 import java.time.Duration;
 import java.util.ArrayList;
@@ -16,18 +14,19 @@ import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.stream.Collectors;
 import org.apache.kafka.common.Cluster;
-import org.astraea.common.Utils;
-import org.astraea.cost.ClusterInfo;
-import org.astraea.cost.NodeInfo;
-import org.astraea.cost.Periodic;
-import org.astraea.cost.ReplicaInfo;
-import org.astraea.cost.broker.NeutralIntegratedCost;
-import org.astraea.metrics.HasBeanObject;
-import org.astraea.metrics.collector.BeanCollector;
-import org.astraea.metrics.collector.Receiver;
-import org.astraea.metrics.jmx.MBeanClient;
-import org.astraea.partitioner.Configuration;
-import org.astraea.partitioner.Dispatcher;
+import org.astraea.app.common.Utils;
+import org.astraea.app.cost.ClusterInfo;
+import org.astraea.app.cost.NodeInfo;
+import org.astraea.app.cost.Periodic;
+import org.astraea.app.cost.ReplicaInfo;
+import org.astraea.app.cost.broker.NeutralIntegratedCost;
+import org.astraea.app.metrics.HasBeanObject;
+import org.astraea.app.metrics.collector.BeanCollector;
+import org.astraea.app.metrics.collector.Receiver;
+import org.astraea.app.metrics.jmx.MBeanClient;
+import org.astraea.app.partitioner.Configuration;
+import org.astraea.app.partitioner.Dispatcher;
+import org.astraea.app.partitioner.PartitionerUtils;
 
 public class SmoothWeightRoundRobinDispatcher extends Periodic<Map<Integer, Double>>
     implements Dispatcher {
@@ -102,7 +101,7 @@ public class SmoothWeightRoundRobinDispatcher extends Periodic<Map<Integer, Doub
 
   @Override
   public void configure(Map<String, ?> configs) {
-    var properties = partitionerConfig(configs);
+    var properties = PartitionerUtils.partitionerConfig(configs);
     var config =
         Configuration.of(
             properties.entrySet().stream()
diff --git a/app/src/main/java/org/astraea/performance/DataSupplier.java b/app/src/main/java/org/astraea/app/performance/DataSupplier.java
similarity index 97%
rename from app/src/main/java/org/astraea/performance/DataSupplier.java
rename to app/src/main/java/org/astraea/app/performance/DataSupplier.java
index 9c6b5538..c8de8bd9 100644
--- a/app/src/main/java/org/astraea/performance/DataSupplier.java
+++ b/app/src/main/java/org/astraea/app/performance/DataSupplier.java
@@ -1,11 +1,11 @@
-package org.astraea.performance;
+package org.astraea.app.performance;
 
 import java.util.Arrays;
 import java.util.Random;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.function.Supplier;
-import org.astraea.common.DataSize;
-import org.astraea.common.DataUnit;
+import org.astraea.app.common.DataSize;
+import org.astraea.app.common.DataUnit;
 
 @FunctionalInterface
 interface DataSupplier extends Supplier<DataSupplier.Data> {
diff --git a/app/src/main/java/org/astraea/performance/DistributionType.java b/app/src/main/java/org/astraea/app/performance/DistributionType.java
similarity index 97%
rename from app/src/main/java/org/astraea/performance/DistributionType.java
rename to app/src/main/java/org/astraea/app/performance/DistributionType.java
index 15918a7e..7664c551 100644
--- a/app/src/main/java/org/astraea/performance/DistributionType.java
+++ b/app/src/main/java/org/astraea/app/performance/DistributionType.java
@@ -1,4 +1,4 @@
-package org.astraea.performance;
+package org.astraea.app.performance;
 
 import com.beust.jcommander.ParameterException;
 import java.util.ArrayList;
@@ -6,7 +6,7 @@ import java.util.Arrays;
 import java.util.Random;
 import java.util.function.Supplier;
 import java.util.stream.IntStream;
-import org.astraea.argument.Field;
+import org.astraea.app.argument.Field;
 
 /**
  * Random distribution generator. Example: {@code Supplier<long> uniformDistribution =
diff --git a/app/src/main/java/org/astraea/performance/ExeTime.java b/app/src/main/java/org/astraea/app/performance/ExeTime.java
similarity index 91%
rename from app/src/main/java/org/astraea/performance/ExeTime.java
rename to app/src/main/java/org/astraea/app/performance/ExeTime.java
index 945765aa..6a2494e1 100644
--- a/app/src/main/java/org/astraea/performance/ExeTime.java
+++ b/app/src/main/java/org/astraea/app/performance/ExeTime.java
@@ -1,10 +1,10 @@
-package org.astraea.performance;
+package org.astraea.app.performance;
 
 import com.beust.jcommander.ParameterException;
 import java.time.Duration;
 import java.util.function.BiFunction;
 import java.util.regex.Pattern;
-import org.astraea.argument.DurationField;
+import org.astraea.app.argument.DurationField;
 
 /**
  * Two kind of running modes. One runs for a duration of time. The other runs for a number of
@@ -37,7 +37,7 @@ interface ExeTime {
     };
   }
 
-  class Field extends org.astraea.argument.Field<ExeTime> {
+  class Field extends org.astraea.app.argument.Field<ExeTime> {
     static final Pattern PATTERN = Pattern.compile("^([0-9]+)(days|day|h|m|s|ms|us|ns|records)$");
 
     @Override
diff --git a/app/src/main/java/org/astraea/performance/Manager.java b/app/src/main/java/org/astraea/app/performance/Manager.java
similarity index 96%
rename from app/src/main/java/org/astraea/performance/Manager.java
rename to app/src/main/java/org/astraea/app/performance/Manager.java
index fac125cb..59b834f5 100644
--- a/app/src/main/java/org/astraea/performance/Manager.java
+++ b/app/src/main/java/org/astraea/app/performance/Manager.java
@@ -1,8 +1,8 @@
-package org.astraea.performance;
+package org.astraea.app.performance;
 
 import java.util.List;
 import java.util.function.Supplier;
-import org.astraea.common.DataUnit;
+import org.astraea.app.common.DataUnit;
 
 /**
  * Thread safe This class is used for managing the start/end of the producer/consumer threads.
diff --git a/app/src/main/java/org/astraea/performance/Metrics.java b/app/src/main/java/org/astraea/app/performance/Metrics.java
similarity index 97%
rename from app/src/main/java/org/astraea/performance/Metrics.java
rename to app/src/main/java/org/astraea/app/performance/Metrics.java
index 90ebedbc..8031109d 100644
--- a/app/src/main/java/org/astraea/performance/Metrics.java
+++ b/app/src/main/java/org/astraea/app/performance/Metrics.java
@@ -1,4 +1,4 @@
-package org.astraea.performance;
+package org.astraea.app.performance;
 
 import java.util.function.BiConsumer;
 
diff --git a/app/src/main/java/org/astraea/performance/Performance.java b/app/src/main/java/org/astraea/app/performance/Performance.java
similarity index 93%
rename from app/src/main/java/org/astraea/performance/Performance.java
rename to app/src/main/java/org/astraea/app/performance/Performance.java
index adb10730..209ccdf4 100644
--- a/app/src/main/java/org/astraea/performance/Performance.java
+++ b/app/src/main/java/org/astraea/app/performance/Performance.java
@@ -1,4 +1,4 @@
-package org.astraea.performance;
+package org.astraea.app.performance;
 
 import com.beust.jcommander.Parameter;
 import java.io.IOException;
@@ -17,24 +17,24 @@ import java.util.stream.Collectors;
 import java.util.stream.IntStream;
 import org.apache.kafka.clients.producer.internals.DefaultPartitioner;
 import org.apache.kafka.common.errors.WakeupException;
-import org.astraea.admin.Admin;
-import org.astraea.admin.Compression;
-import org.astraea.admin.TopicPartition;
-import org.astraea.argument.CompressionField;
-import org.astraea.argument.NonEmptyStringField;
-import org.astraea.argument.NonNegativeShortField;
-import org.astraea.argument.PathField;
-import org.astraea.argument.PositiveLongField;
-import org.astraea.argument.PositiveShortField;
-import org.astraea.common.DataSize;
-import org.astraea.common.DataUnit;
-import org.astraea.common.Utils;
-import org.astraea.concurrent.Executor;
-import org.astraea.concurrent.State;
-import org.astraea.concurrent.ThreadPool;
-import org.astraea.consumer.Consumer;
-import org.astraea.consumer.Isolation;
-import org.astraea.producer.Producer;
+import org.astraea.app.admin.Admin;
+import org.astraea.app.admin.Compression;
+import org.astraea.app.admin.TopicPartition;
+import org.astraea.app.argument.CompressionField;
+import org.astraea.app.argument.NonEmptyStringField;
+import org.astraea.app.argument.NonNegativeShortField;
+import org.astraea.app.argument.PathField;
+import org.astraea.app.argument.PositiveLongField;
+import org.astraea.app.argument.PositiveShortField;
+import org.astraea.app.common.DataSize;
+import org.astraea.app.common.DataUnit;
+import org.astraea.app.common.Utils;
+import org.astraea.app.concurrent.Executor;
+import org.astraea.app.concurrent.State;
+import org.astraea.app.concurrent.ThreadPool;
+import org.astraea.app.consumer.Consumer;
+import org.astraea.app.consumer.Isolation;
+import org.astraea.app.producer.Producer;
 
 /**
  * Performance benchmark which includes
@@ -66,7 +66,7 @@ public class Performance {
   /** Used in Automation, to achieve the end of one Performance and then start another. */
   public static void main(String[] args)
       throws InterruptedException, IOException, ExecutionException {
-    execute(org.astraea.argument.Argument.parse(new Argument(), args));
+    execute(org.astraea.app.argument.Argument.parse(new Argument(), args));
   }
 
   private static DataSupplier dataSupplier(Performance.Argument argument) {
@@ -249,7 +249,7 @@ public class Performance {
     return param.specifyBroker.stream().allMatch(broker -> broker >= 0);
   }
 
-  public static class Argument extends org.astraea.argument.Argument {
+  public static class Argument extends org.astraea.app.argument.Argument {
 
     @Parameter(
         names = {"--topic"},
diff --git a/app/src/main/java/org/astraea/performance/ProducerExecutor.java b/app/src/main/java/org/astraea/app/performance/ProducerExecutor.java
similarity index 95%
rename from app/src/main/java/org/astraea/performance/ProducerExecutor.java
rename to app/src/main/java/org/astraea/app/performance/ProducerExecutor.java
index a248c22d..787e16bc 100644
--- a/app/src/main/java/org/astraea/performance/ProducerExecutor.java
+++ b/app/src/main/java/org/astraea/app/performance/ProducerExecutor.java
@@ -1,4 +1,4 @@
-package org.astraea.performance;
+package org.astraea.app.performance;
 
 import java.time.Duration;
 import java.util.List;
@@ -7,11 +7,11 @@ import java.util.function.BiConsumer;
 import java.util.function.Supplier;
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
-import org.astraea.common.Utils;
-import org.astraea.concurrent.Executor;
-import org.astraea.concurrent.State;
-import org.astraea.producer.Producer;
-import org.astraea.producer.Sender;
+import org.astraea.app.common.Utils;
+import org.astraea.app.concurrent.Executor;
+import org.astraea.app.concurrent.State;
+import org.astraea.app.producer.Producer;
+import org.astraea.app.producer.Sender;
 
 abstract class ProducerExecutor implements Executor {
 
diff --git a/app/src/main/java/org/astraea/performance/ReportFormat.java b/app/src/main/java/org/astraea/app/performance/ReportFormat.java
similarity index 97%
rename from app/src/main/java/org/astraea/performance/ReportFormat.java
rename to app/src/main/java/org/astraea/app/performance/ReportFormat.java
index 7a0b6200..973349bf 100644
--- a/app/src/main/java/org/astraea/performance/ReportFormat.java
+++ b/app/src/main/java/org/astraea/app/performance/ReportFormat.java
@@ -1,4 +1,4 @@
-package org.astraea.performance;
+package org.astraea.app.performance;
 
 import com.beust.jcommander.IStringConverter;
 import com.beust.jcommander.ParameterException;
@@ -12,10 +12,10 @@ import java.time.Duration;
 import java.util.Date;
 import java.util.function.Supplier;
 import java.util.stream.IntStream;
-import org.astraea.common.DataUnit;
-import org.astraea.common.Utils;
-import org.astraea.concurrent.Executor;
-import org.astraea.concurrent.State;
+import org.astraea.app.common.DataUnit;
+import org.astraea.app.common.Utils;
+import org.astraea.app.concurrent.Executor;
+import org.astraea.app.concurrent.State;
 
 public enum ReportFormat {
   CSV("csv"),
diff --git a/app/src/main/java/org/astraea/performance/Tracker.java b/app/src/main/java/org/astraea/app/performance/Tracker.java
similarity index 97%
rename from app/src/main/java/org/astraea/performance/Tracker.java
rename to app/src/main/java/org/astraea/app/performance/Tracker.java
index 1c968a1d..09aeefa6 100644
--- a/app/src/main/java/org/astraea/performance/Tracker.java
+++ b/app/src/main/java/org/astraea/app/performance/Tracker.java
@@ -1,13 +1,13 @@
-package org.astraea.performance;
+package org.astraea.app.performance;
 
 import java.time.Duration;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.function.Supplier;
-import org.astraea.common.DataUnit;
-import org.astraea.concurrent.Executor;
-import org.astraea.concurrent.State;
+import org.astraea.app.common.DataUnit;
+import org.astraea.app.concurrent.Executor;
+import org.astraea.app.concurrent.State;
 
 /** Print out the given metrics. */
 public class Tracker implements Executor {
diff --git a/app/src/main/java/org/astraea/producer/AbstractSender.java b/app/src/main/java/org/astraea/app/producer/AbstractSender.java
similarity index 94%
rename from app/src/main/java/org/astraea/producer/AbstractSender.java
rename to app/src/main/java/org/astraea/app/producer/AbstractSender.java
index 05577a18..ba28695a 100644
--- a/app/src/main/java/org/astraea/producer/AbstractSender.java
+++ b/app/src/main/java/org/astraea/app/producer/AbstractSender.java
@@ -1,10 +1,10 @@
-package org.astraea.producer;
+package org.astraea.app.producer;
 
 import java.util.Collection;
 import java.util.List;
 import java.util.Objects;
 import org.apache.kafka.clients.producer.ProducerRecord;
-import org.astraea.consumer.Header;
+import org.astraea.app.consumer.Header;
 
 abstract class AbstractSender<Key, Value> implements Sender<Key, Value> {
   protected Key key;
diff --git a/app/src/main/java/org/astraea/producer/Builder.java b/app/src/main/java/org/astraea/app/producer/Builder.java
similarity index 98%
rename from app/src/main/java/org/astraea/producer/Builder.java
rename to app/src/main/java/org/astraea/app/producer/Builder.java
index a3a70d93..b8e48125 100644
--- a/app/src/main/java/org/astraea/producer/Builder.java
+++ b/app/src/main/java/org/astraea/app/producer/Builder.java
@@ -1,4 +1,4 @@
-package org.astraea.producer;
+package org.astraea.app.producer;
 
 import java.util.Collection;
 import java.util.HashMap;
@@ -16,7 +16,7 @@ import org.apache.kafka.common.KafkaException;
 import org.apache.kafka.common.errors.AuthorizationException;
 import org.apache.kafka.common.errors.OutOfOrderSequenceException;
 import org.apache.kafka.common.errors.ProducerFencedException;
-import org.astraea.admin.Compression;
+import org.astraea.app.admin.Compression;
 
 public class Builder<Key, Value> {
   private final Map<String, Object> configs = new HashMap<>();
diff --git a/app/src/main/java/org/astraea/producer/Metadata.java b/app/src/main/java/org/astraea/app/producer/Metadata.java
similarity index 98%
rename from app/src/main/java/org/astraea/producer/Metadata.java
rename to app/src/main/java/org/astraea/app/producer/Metadata.java
index a3b1cb56..ae93b961 100644
--- a/app/src/main/java/org/astraea/producer/Metadata.java
+++ b/app/src/main/java/org/astraea/app/producer/Metadata.java
@@ -1,4 +1,4 @@
-package org.astraea.producer;
+package org.astraea.app.producer;
 
 import org.apache.kafka.clients.producer.RecordMetadata;
 
diff --git a/app/src/main/java/org/astraea/producer/Producer.java b/app/src/main/java/org/astraea/app/producer/Producer.java
similarity index 97%
rename from app/src/main/java/org/astraea/producer/Producer.java
rename to app/src/main/java/org/astraea/app/producer/Producer.java
index 5921cf3a..69f72da8 100644
--- a/app/src/main/java/org/astraea/producer/Producer.java
+++ b/app/src/main/java/org/astraea/app/producer/Producer.java
@@ -1,4 +1,4 @@
-package org.astraea.producer;
+package org.astraea.app.producer;
 
 import java.util.Collection;
 import java.util.Map;
diff --git a/app/src/main/java/org/astraea/producer/Sender.java b/app/src/main/java/org/astraea/app/producer/Sender.java
similarity index 91%
rename from app/src/main/java/org/astraea/producer/Sender.java
rename to app/src/main/java/org/astraea/app/producer/Sender.java
index 9c48cd59..77ca0594 100644
--- a/app/src/main/java/org/astraea/producer/Sender.java
+++ b/app/src/main/java/org/astraea/app/producer/Sender.java
@@ -1,8 +1,8 @@
-package org.astraea.producer;
+package org.astraea.app.producer;
 
 import java.util.Collection;
 import java.util.concurrent.CompletionStage;
-import org.astraea.consumer.Header;
+import org.astraea.app.consumer.Header;
 
 public interface Sender<Key, Value> {
   Sender<Key, Value> key(Key key);
diff --git a/app/src/main/java/org/astraea/producer/Serializer.java b/app/src/main/java/org/astraea/app/producer/Serializer.java
similarity index 96%
rename from app/src/main/java/org/astraea/producer/Serializer.java
rename to app/src/main/java/org/astraea/app/producer/Serializer.java
index a7fdc085..ce99c907 100644
--- a/app/src/main/java/org/astraea/producer/Serializer.java
+++ b/app/src/main/java/org/astraea/app/producer/Serializer.java
@@ -1,4 +1,4 @@
-package org.astraea.producer;
+package org.astraea.app.producer;
 
 import java.util.Collection;
 import java.util.List;
@@ -9,7 +9,7 @@ import org.apache.kafka.common.serialization.FloatSerializer;
 import org.apache.kafka.common.serialization.IntegerSerializer;
 import org.apache.kafka.common.serialization.LongSerializer;
 import org.apache.kafka.common.serialization.StringSerializer;
-import org.astraea.consumer.Header;
+import org.astraea.app.consumer.Header;
 
 @FunctionalInterface
 public interface Serializer<T> {
diff --git a/app/src/main/java/org/astraea/web/BrokerHandler.java b/app/src/main/java/org/astraea/app/web/BrokerHandler.java
similarity index 93%
rename from app/src/main/java/org/astraea/web/BrokerHandler.java
rename to app/src/main/java/org/astraea/app/web/BrokerHandler.java
index b40f7727..3155c46f 100644
--- a/app/src/main/java/org/astraea/web/BrokerHandler.java
+++ b/app/src/main/java/org/astraea/app/web/BrokerHandler.java
@@ -1,4 +1,4 @@
-package org.astraea.web;
+package org.astraea.app.web;
 
 import java.util.List;
 import java.util.Map;
@@ -7,9 +7,9 @@ import java.util.Optional;
 import java.util.Set;
 import java.util.stream.Collectors;
 import java.util.stream.StreamSupport;
-import org.astraea.admin.Admin;
-import org.astraea.admin.Config;
-import org.astraea.admin.TopicPartition;
+import org.astraea.app.admin.Admin;
+import org.astraea.app.admin.Config;
+import org.astraea.app.admin.TopicPartition;
 
 class BrokerHandler implements Handler {
 
diff --git a/app/src/main/java/org/astraea/web/ErrorObject.java b/app/src/main/java/org/astraea/app/web/ErrorObject.java
similarity index 95%
rename from app/src/main/java/org/astraea/web/ErrorObject.java
rename to app/src/main/java/org/astraea/app/web/ErrorObject.java
index 834e678e..04b50f27 100644
--- a/app/src/main/java/org/astraea/web/ErrorObject.java
+++ b/app/src/main/java/org/astraea/app/web/ErrorObject.java
@@ -1,4 +1,4 @@
-package org.astraea.web;
+package org.astraea.app.web;
 
 import java.util.NoSuchElementException;
 
diff --git a/app/src/main/java/org/astraea/web/GroupHandler.java b/app/src/main/java/org/astraea/app/web/GroupHandler.java
similarity index 98%
rename from app/src/main/java/org/astraea/web/GroupHandler.java
rename to app/src/main/java/org/astraea/app/web/GroupHandler.java
index f3b33206..fe4ad412 100644
--- a/app/src/main/java/org/astraea/web/GroupHandler.java
+++ b/app/src/main/java/org/astraea/app/web/GroupHandler.java
@@ -1,11 +1,11 @@
-package org.astraea.web;
+package org.astraea.app.web;
 
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
 import java.util.stream.Collectors;
-import org.astraea.admin.Admin;
+import org.astraea.app.admin.Admin;
 
 public class GroupHandler implements Handler {
 
diff --git a/app/src/main/java/org/astraea/web/Handler.java b/app/src/main/java/org/astraea/app/web/Handler.java
similarity index 99%
rename from app/src/main/java/org/astraea/web/Handler.java
rename to app/src/main/java/org/astraea/app/web/Handler.java
index d9efb078..ae11e810 100644
--- a/app/src/main/java/org/astraea/web/Handler.java
+++ b/app/src/main/java/org/astraea/app/web/Handler.java
@@ -1,4 +1,4 @@
-package org.astraea.web;
+package org.astraea.app.web;
 
 import com.sun.net.httpserver.HttpExchange;
 import com.sun.net.httpserver.HttpHandler;
diff --git a/app/src/main/java/org/astraea/web/JsonObject.java b/app/src/main/java/org/astraea/app/web/JsonObject.java
similarity index 80%
rename from app/src/main/java/org/astraea/web/JsonObject.java
rename to app/src/main/java/org/astraea/app/web/JsonObject.java
index f3d6fe0c..063fd1c8 100644
--- a/app/src/main/java/org/astraea/web/JsonObject.java
+++ b/app/src/main/java/org/astraea/app/web/JsonObject.java
@@ -1,4 +1,4 @@
-package org.astraea.web;
+package org.astraea.app.web;
 
 import com.google.gson.Gson;
 
diff --git a/app/src/main/java/org/astraea/web/PipelineHandler.java b/app/src/main/java/org/astraea/app/web/PipelineHandler.java
similarity index 96%
rename from app/src/main/java/org/astraea/web/PipelineHandler.java
rename to app/src/main/java/org/astraea/app/web/PipelineHandler.java
index 851f15ce..409ea54d 100644
--- a/app/src/main/java/org/astraea/web/PipelineHandler.java
+++ b/app/src/main/java/org/astraea/app/web/PipelineHandler.java
@@ -1,4 +1,4 @@
-package org.astraea.web;
+package org.astraea.app.web;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -8,9 +8,9 @@ import java.util.Optional;
 import java.util.function.Function;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
-import org.astraea.admin.Admin;
-import org.astraea.admin.Member;
-import org.astraea.admin.ProducerState;
+import org.astraea.app.admin.Admin;
+import org.astraea.app.admin.Member;
+import org.astraea.app.admin.ProducerState;
 
 class PipelineHandler implements Handler {
 
diff --git a/app/src/main/java/org/astraea/web/PostRequest.java b/app/src/main/java/org/astraea/app/web/PostRequest.java
similarity index 98%
rename from app/src/main/java/org/astraea/web/PostRequest.java
rename to app/src/main/java/org/astraea/app/web/PostRequest.java
index e3254cd2..9db7ceb7 100644
--- a/app/src/main/java/org/astraea/web/PostRequest.java
+++ b/app/src/main/java/org/astraea/app/web/PostRequest.java
@@ -1,4 +1,4 @@
-package org.astraea.web;
+package org.astraea.app.web;
 
 import com.google.gson.Gson;
 import com.sun.net.httpserver.HttpExchange;
diff --git a/app/src/main/java/org/astraea/web/ProducerHandler.java b/app/src/main/java/org/astraea/app/web/ProducerHandler.java
similarity index 96%
rename from app/src/main/java/org/astraea/web/ProducerHandler.java
rename to app/src/main/java/org/astraea/app/web/ProducerHandler.java
index 7228773e..e4a2bafc 100644
--- a/app/src/main/java/org/astraea/web/ProducerHandler.java
+++ b/app/src/main/java/org/astraea/app/web/ProducerHandler.java
@@ -1,12 +1,12 @@
-package org.astraea.web;
+package org.astraea.app.web;
 
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
 import java.util.stream.Collectors;
-import org.astraea.admin.Admin;
-import org.astraea.admin.TopicPartition;
+import org.astraea.app.admin.Admin;
+import org.astraea.app.admin.TopicPartition;
 
 class ProducerHandler implements Handler {
 
diff --git a/app/src/main/java/org/astraea/web/QuotaHandler.java b/app/src/main/java/org/astraea/app/web/QuotaHandler.java
similarity index 70%
rename from app/src/main/java/org/astraea/web/QuotaHandler.java
rename to app/src/main/java/org/astraea/app/web/QuotaHandler.java
index fd7c73f9..1f7b1724 100644
--- a/app/src/main/java/org/astraea/web/QuotaHandler.java
+++ b/app/src/main/java/org/astraea/app/web/QuotaHandler.java
@@ -1,23 +1,22 @@
-package org.astraea.web;
+package org.astraea.app.web;
 
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 import java.util.stream.Collectors;
-import org.astraea.admin.Admin;
-import org.astraea.admin.Quota;
+import org.astraea.app.admin.Admin;
 
 public class QuotaHandler implements Handler {
 
-  static final String IP_KEY = org.astraea.admin.Quota.Target.IP.nameOfKafka();
-  static final String CLIENT_ID_KEY = org.astraea.admin.Quota.Target.CLIENT_ID.nameOfKafka();
+  static final String IP_KEY = org.astraea.app.admin.Quota.Target.IP.nameOfKafka();
+  static final String CLIENT_ID_KEY = org.astraea.app.admin.Quota.Target.CLIENT_ID.nameOfKafka();
   static final String CONNECTION_RATE_KEY =
-      org.astraea.admin.Quota.Limit.IP_CONNECTION_RATE.nameOfKafka();
+      org.astraea.app.admin.Quota.Limit.IP_CONNECTION_RATE.nameOfKafka();
   static final String PRODUCE_RATE_KEY =
-      org.astraea.admin.Quota.Limit.PRODUCER_BYTE_RATE.nameOfKafka();
+      org.astraea.app.admin.Quota.Limit.PRODUCER_BYTE_RATE.nameOfKafka();
   static final String CONSUME_RATE_KEY =
-      org.astraea.admin.Quota.Limit.CONSUMER_BYTE_RATE.nameOfKafka();
+      org.astraea.app.admin.Quota.Limit.CONSUMER_BYTE_RATE.nameOfKafka();
 
   private final Admin admin;
 
@@ -28,10 +27,10 @@ public class QuotaHandler implements Handler {
   @Override
   public Quotas get(Optional<String> target, Map<String, String> queries) {
     if (queries.containsKey(IP_KEY))
-      return new Quotas(admin.quotas(org.astraea.admin.Quota.Target.IP, queries.get(IP_KEY)));
+      return new Quotas(admin.quotas(org.astraea.app.admin.Quota.Target.IP, queries.get(IP_KEY)));
     if (queries.containsKey(CLIENT_ID_KEY))
       return new Quotas(
-          admin.quotas(org.astraea.admin.Quota.Target.CLIENT_ID, queries.get(CLIENT_ID_KEY)));
+          admin.quotas(org.astraea.app.admin.Quota.Target.CLIENT_ID, queries.get(CLIENT_ID_KEY)));
     return new Quotas(admin.quotas());
   }
 
@@ -43,7 +42,7 @@ public class QuotaHandler implements Handler {
           .ip(request.value(IP_KEY))
           .connectionRate(request.intValue(CONNECTION_RATE_KEY, Integer.MAX_VALUE))
           .create();
-      return new Quotas(admin.quotas(org.astraea.admin.Quota.Target.IP, request.value(IP_KEY)));
+      return new Quotas(admin.quotas(org.astraea.app.admin.Quota.Target.IP, request.value(IP_KEY)));
     }
     if (request.get(CLIENT_ID_KEY).isPresent()) {
       admin
@@ -53,7 +52,7 @@ public class QuotaHandler implements Handler {
           .consumeRate(request.intValue(CONSUME_RATE_KEY, Integer.MAX_VALUE))
           .create();
       return new Quotas(
-          admin.quotas(org.astraea.admin.Quota.Target.CLIENT_ID, request.value(CLIENT_ID_KEY)));
+          admin.quotas(org.astraea.app.admin.Quota.Target.CLIENT_ID, request.value(CLIENT_ID_KEY)));
     }
     return ErrorObject.for404("You must define either " + CLIENT_ID_KEY + " or " + IP_KEY);
   }
@@ -82,7 +81,7 @@ public class QuotaHandler implements Handler {
     final Target target;
     final Limit limit;
 
-    public Quota(org.astraea.admin.Quota quota) {
+    public Quota(org.astraea.app.admin.Quota quota) {
       this(
           quota.target().nameOfKafka(),
           quota.targetValue(),
@@ -99,7 +98,7 @@ public class QuotaHandler implements Handler {
   static class Quotas implements JsonObject {
     final List<Quota> quotas;
 
-    Quotas(Collection<org.astraea.admin.Quota> quotas) {
+    Quotas(Collection<org.astraea.app.admin.Quota> quotas) {
       this.quotas = quotas.stream().map(Quota::new).collect(Collectors.toUnmodifiableList());
     }
   }
diff --git a/app/src/main/java/org/astraea/web/TopicHandler.java b/app/src/main/java/org/astraea/app/web/TopicHandler.java
similarity index 96%
rename from app/src/main/java/org/astraea/web/TopicHandler.java
rename to app/src/main/java/org/astraea/app/web/TopicHandler.java
index 44e59c00..30faaa92 100644
--- a/app/src/main/java/org/astraea/web/TopicHandler.java
+++ b/app/src/main/java/org/astraea/app/web/TopicHandler.java
@@ -1,4 +1,4 @@
-package org.astraea.web;
+package org.astraea.app.web;
 
 import java.util.Collection;
 import java.util.HashMap;
@@ -9,8 +9,8 @@ import java.util.Set;
 import java.util.stream.Collectors;
 import java.util.stream.StreamSupport;
 import org.apache.kafka.common.errors.UnknownTopicOrPartitionException;
-import org.astraea.admin.Admin;
-import org.astraea.admin.Config;
+import org.astraea.app.admin.Admin;
+import org.astraea.app.admin.Config;
 
 class TopicHandler implements Handler {
 
@@ -141,7 +141,7 @@ class TopicHandler implements Handler {
     final boolean isFuture;
     final String path;
 
-    Replica(org.astraea.admin.Replica replica) {
+    Replica(org.astraea.app.admin.Replica replica) {
       this(
           replica.broker(),
           replica.lag(),
diff --git a/app/src/main/java/org/astraea/web/WebService.java b/app/src/main/java/org/astraea/app/web/WebService.java
similarity index 80%
rename from app/src/main/java/org/astraea/web/WebService.java
rename to app/src/main/java/org/astraea/app/web/WebService.java
index c47cf379..029e0c90 100644
--- a/app/src/main/java/org/astraea/web/WebService.java
+++ b/app/src/main/java/org/astraea/app/web/WebService.java
@@ -1,16 +1,16 @@
-package org.astraea.web;
+package org.astraea.app.web;
 
 import com.beust.jcommander.Parameter;
 import com.sun.net.httpserver.HttpServer;
 import java.io.IOException;
 import java.net.InetSocketAddress;
-import org.astraea.admin.Admin;
-import org.astraea.argument.NonNegativeIntegerField;
+import org.astraea.app.admin.Admin;
+import org.astraea.app.argument.NonNegativeIntegerField;
 
 public class WebService {
 
   public static void main(String[] args) throws Exception {
-    execute(org.astraea.argument.Argument.parse(new Argument(), args));
+    execute(org.astraea.app.argument.Argument.parse(new Argument(), args));
   }
 
   private static void execute(Argument arg) throws IOException {
@@ -24,7 +24,7 @@ public class WebService {
     server.start();
   }
 
-  static class Argument extends org.astraea.argument.Argument {
+  static class Argument extends org.astraea.app.argument.Argument {
     @Parameter(
         names = {"--port"},
         description = "Integer: the port to bind",


Test patch:
diff --git a/app/src/test/java/org/astraea/AppTest.java b/app/src/test/java/org/astraea/app/AppTest.java
similarity index 95%
rename from app/src/test/java/org/astraea/AppTest.java
rename to app/src/test/java/org/astraea/app/AppTest.java
index 95ad5977..19b5856e 100644
--- a/app/src/test/java/org/astraea/AppTest.java
+++ b/app/src/test/java/org/astraea/app/AppTest.java
@@ -1,4 +1,4 @@
-package org.astraea;
+package org.astraea.app;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
diff --git a/app/src/test/java/org/astraea/admin/AdminTest.java b/app/src/test/java/org/astraea/app/admin/AdminTest.java
similarity index 98%
rename from app/src/test/java/org/astraea/admin/AdminTest.java
rename to app/src/test/java/org/astraea/app/admin/AdminTest.java
index 605a27c0..1b42c015 100644
--- a/app/src/test/java/org/astraea/admin/AdminTest.java
+++ b/app/src/test/java/org/astraea/app/admin/AdminTest.java
@@ -1,4 +1,4 @@
-package org.astraea.admin;
+package org.astraea.app.admin;
 
 import static org.junit.jupiter.api.condition.OS.WINDOWS;
 
@@ -14,12 +14,12 @@ import java.util.stream.Collectors;
 import java.util.stream.IntStream;
 import java.util.stream.StreamSupport;
 import org.apache.kafka.common.config.TopicConfig;
-import org.astraea.common.Utils;
-import org.astraea.consumer.Consumer;
-import org.astraea.consumer.Deserializer;
-import org.astraea.producer.Producer;
-import org.astraea.producer.Serializer;
-import org.astraea.service.RequireBrokerCluster;
+import org.astraea.app.common.Utils;
+import org.astraea.app.consumer.Consumer;
+import org.astraea.app.consumer.Deserializer;
+import org.astraea.app.producer.Producer;
+import org.astraea.app.producer.Serializer;
+import org.astraea.app.service.RequireBrokerCluster;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.condition.DisabledOnOs;
diff --git a/app/src/test/java/org/astraea/admin/CompressionTest.java b/app/src/test/java/org/astraea/app/admin/CompressionTest.java
similarity index 94%
rename from app/src/test/java/org/astraea/admin/CompressionTest.java
rename to app/src/test/java/org/astraea/app/admin/CompressionTest.java
index cf121f3c..e897f0de 100644
--- a/app/src/test/java/org/astraea/admin/CompressionTest.java
+++ b/app/src/test/java/org/astraea/app/admin/CompressionTest.java
@@ -1,4 +1,4 @@
-package org.astraea.admin;
+package org.astraea.app.admin;
 
 import java.util.Arrays;
 import org.apache.kafka.common.record.CompressionType;
diff --git a/app/src/test/java/org/astraea/admin/QuotaTest.java b/app/src/test/java/org/astraea/app/admin/QuotaTest.java
similarity index 93%
rename from app/src/test/java/org/astraea/admin/QuotaTest.java
rename to app/src/test/java/org/astraea/app/admin/QuotaTest.java
index 0a1ac33f..3af1b3b7 100644
--- a/app/src/test/java/org/astraea/admin/QuotaTest.java
+++ b/app/src/test/java/org/astraea/app/admin/QuotaTest.java
@@ -1,4 +1,4 @@
-package org.astraea.admin;
+package org.astraea.app.admin;
 
 import java.util.Arrays;
 import org.junit.jupiter.api.Assertions;
diff --git a/app/src/test/java/org/astraea/admin/ReplicaCollieTest.java b/app/src/test/java/org/astraea/app/admin/ReplicaCollieTest.java
similarity index 97%
rename from app/src/test/java/org/astraea/admin/ReplicaCollieTest.java
rename to app/src/test/java/org/astraea/app/admin/ReplicaCollieTest.java
index ac946b17..db8b1b8b 100644
--- a/app/src/test/java/org/astraea/admin/ReplicaCollieTest.java
+++ b/app/src/test/java/org/astraea/app/admin/ReplicaCollieTest.java
@@ -1,4 +1,4 @@
-package org.astraea.admin;
+package org.astraea.app.admin;
 
 import static org.junit.jupiter.api.condition.OS.WINDOWS;
 
@@ -8,9 +8,9 @@ import java.util.Set;
 import java.util.TreeMap;
 import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
-import org.astraea.argument.Argument;
-import org.astraea.common.Utils;
-import org.astraea.service.RequireBrokerCluster;
+import org.astraea.app.argument.Argument;
+import org.astraea.app.common.Utils;
+import org.astraea.app.service.RequireBrokerCluster;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.condition.DisabledOnOs;
diff --git a/app/src/test/java/org/astraea/admin/ReplicaSyncingMonitorIntegrationTest.java b/app/src/test/java/org/astraea/app/admin/ReplicaSyncingMonitorIntegrationTest.java
similarity index 92%
rename from app/src/test/java/org/astraea/admin/ReplicaSyncingMonitorIntegrationTest.java
rename to app/src/test/java/org/astraea/app/admin/ReplicaSyncingMonitorIntegrationTest.java
index 3086aebb..5b5e7ec9 100644
--- a/app/src/test/java/org/astraea/admin/ReplicaSyncingMonitorIntegrationTest.java
+++ b/app/src/test/java/org/astraea/app/admin/ReplicaSyncingMonitorIntegrationTest.java
@@ -1,4 +1,4 @@
-package org.astraea.admin;
+package org.astraea.app.admin;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertSame;
@@ -9,9 +9,10 @@ import java.util.Set;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.TimeUnit;
 import java.util.stream.IntStream;
-import org.astraea.producer.Producer;
-import org.astraea.producer.Sender;
-import org.astraea.service.RequireBrokerCluster;
+import org.astraea.app.argument.Argument;
+import org.astraea.app.producer.Producer;
+import org.astraea.app.producer.Sender;
+import org.astraea.app.service.RequireBrokerCluster;
 import org.junit.jupiter.api.Test;
 
 class ReplicaSyncingMonitorIntegrationTest extends RequireBrokerCluster {
@@ -53,7 +54,7 @@ class ReplicaSyncingMonitorIntegrationTest extends RequireBrokerCluster {
                 topicAdmin.migrator().partition(TOPIC_NAME, 0).moveTo(List.of(moveToBroker));
                 ReplicaSyncingMonitor.execute(
                     topicAdmin,
-                    org.astraea.argument.Argument.parse(
+                    Argument.parse(
                         new ReplicaSyncingMonitor.Argument(),
                         new String[] {
                           "--bootstrap.servers",
diff --git a/app/src/test/java/org/astraea/admin/ReplicaSyncingMonitorTest.java b/app/src/test/java/org/astraea/app/admin/ReplicaSyncingMonitorTest.java
similarity index 97%
rename from app/src/test/java/org/astraea/admin/ReplicaSyncingMonitorTest.java
rename to app/src/test/java/org/astraea/app/admin/ReplicaSyncingMonitorTest.java
index 4c78d46b..9f1e566c 100644
--- a/app/src/test/java/org/astraea/admin/ReplicaSyncingMonitorTest.java
+++ b/app/src/test/java/org/astraea/app/admin/ReplicaSyncingMonitorTest.java
@@ -1,4 +1,4 @@
-package org.astraea.admin;
+package org.astraea.app.admin;
 
 import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
 import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -28,7 +28,8 @@ import java.util.function.BiFunction;
 import java.util.function.Consumer;
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
-import org.astraea.common.DataUnit;
+import org.astraea.app.argument.Argument;
+import org.astraea.app.common.DataUnit;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -96,7 +97,7 @@ class ReplicaSyncingMonitorTest {
             () -> {
               ReplicaSyncingMonitor.execute(
                   mockTopicAdmin,
-                  org.astraea.argument.Argument.parse(
+                  Argument.parse(
                       new ReplicaSyncingMonitor.Argument(),
                       new String[] {
                         "--bootstrap.servers", "whatever:9092", "--interval", interval + "ms"
@@ -169,7 +170,7 @@ class ReplicaSyncingMonitorTest {
               try {
                 ReplicaSyncingMonitor.execute(
                     mockTopicAdmin,
-                    org.astraea.argument.Argument.parse(
+                    Argument.parse(
                         new ReplicaSyncingMonitor.Argument(),
                         new String[] {
                           "--bootstrap.servers",
@@ -221,7 +222,7 @@ class ReplicaSyncingMonitorTest {
           try {
             ReplicaSyncingMonitor.execute(
                 mockTopicAdmin,
-                org.astraea.argument.Argument.parse(
+                Argument.parse(
                     new ReplicaSyncingMonitor.Argument(),
                     new String[] {
                       "--bootstrap.servers",
@@ -292,8 +293,7 @@ class ReplicaSyncingMonitorTest {
 
     // act
     Consumer<String[]> execution =
-        (String[] args) ->
-            org.astraea.argument.Argument.parse(new ReplicaSyncingMonitor.Argument(), args);
+        (String[] args) -> Argument.parse(new ReplicaSyncingMonitor.Argument(), args);
 
     // assert
     correct.stream()
diff --git a/app/src/test/java/org/astraea/admin/TopicExplorerTest.java b/app/src/test/java/org/astraea/app/admin/TopicExplorerTest.java
similarity index 98%
rename from app/src/test/java/org/astraea/admin/TopicExplorerTest.java
rename to app/src/test/java/org/astraea/app/admin/TopicExplorerTest.java
index dadd527a..c45f9d28 100644
--- a/app/src/test/java/org/astraea/admin/TopicExplorerTest.java
+++ b/app/src/test/java/org/astraea/app/admin/TopicExplorerTest.java
@@ -1,4 +1,4 @@
-package org.astraea.admin;
+package org.astraea.app.admin;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertThrows;
@@ -19,8 +19,8 @@ import java.util.Set;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 import org.apache.kafka.clients.consumer.ConsumerConfig;
-import org.astraea.consumer.Consumer;
-import org.astraea.service.RequireBrokerCluster;
+import org.astraea.app.consumer.Consumer;
+import org.astraea.app.service.RequireBrokerCluster;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.Test;
 import org.mockito.Mockito;
diff --git a/app/src/test/java/org/astraea/admin/TopicPartitionTest.java b/app/src/test/java/org/astraea/app/admin/TopicPartitionTest.java
similarity index 97%
rename from app/src/test/java/org/astraea/admin/TopicPartitionTest.java
rename to app/src/test/java/org/astraea/app/admin/TopicPartitionTest.java
index 7f8a1151..76651abc 100644
--- a/app/src/test/java/org/astraea/admin/TopicPartitionTest.java
+++ b/app/src/test/java/org/astraea/app/admin/TopicPartitionTest.java
@@ -1,4 +1,4 @@
-package org.astraea.admin;
+package org.astraea.app.admin;
 
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
diff --git a/app/src/test/java/org/astraea/argument/ArgumentTest.java b/app/src/test/java/org/astraea/app/argument/ArgumentTest.java
similarity index 98%
rename from app/src/test/java/org/astraea/argument/ArgumentTest.java
rename to app/src/test/java/org/astraea/app/argument/ArgumentTest.java
index b52fc952..58925d5d 100644
--- a/app/src/test/java/org/astraea/argument/ArgumentTest.java
+++ b/app/src/test/java/org/astraea/app/argument/ArgumentTest.java
@@ -1,4 +1,4 @@
-package org.astraea.argument;
+package org.astraea.app.argument;
 
 import java.io.BufferedWriter;
 import java.io.FileWriter;
diff --git a/app/src/test/java/org/astraea/argument/CompressionFieldTest.java b/app/src/test/java/org/astraea/app/argument/CompressionFieldTest.java
similarity index 81%
rename from app/src/test/java/org/astraea/argument/CompressionFieldTest.java
rename to app/src/test/java/org/astraea/app/argument/CompressionFieldTest.java
index c6648d4f..a314ad54 100644
--- a/app/src/test/java/org/astraea/argument/CompressionFieldTest.java
+++ b/app/src/test/java/org/astraea/app/argument/CompressionFieldTest.java
@@ -1,9 +1,9 @@
-package org.astraea.argument;
+package org.astraea.app.argument;
 
 import com.beust.jcommander.Parameter;
 import com.beust.jcommander.ParameterException;
 import java.util.stream.Stream;
-import org.astraea.admin.Compression;
+import org.astraea.app.admin.Compression;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
@@ -27,8 +27,7 @@ public class CompressionFieldTest {
 
   @Test
   void testParse() {
-    var arg =
-        org.astraea.argument.Argument.parse(new FakeParameter(), new String[] {"--field", "gzip"});
+    var arg = Argument.parse(new FakeParameter(), new String[] {"--field", "gzip"});
     Assertions.assertEquals(Compression.GZIP, arg.value);
   }
 }
diff --git a/app/src/test/java/org/astraea/argument/DurationFieldTest.java b/app/src/test/java/org/astraea/app/argument/DurationFieldTest.java
similarity index 98%
rename from app/src/test/java/org/astraea/argument/DurationFieldTest.java
rename to app/src/test/java/org/astraea/app/argument/DurationFieldTest.java
index 1082746c..da21b42d 100644
--- a/app/src/test/java/org/astraea/argument/DurationFieldTest.java
+++ b/app/src/test/java/org/astraea/app/argument/DurationFieldTest.java
@@ -1,4 +1,4 @@
-package org.astraea.argument;
+package org.astraea.app.argument;
 
 import com.beust.jcommander.ParameterException;
 import java.time.Duration;
diff --git a/app/src/test/java/org/astraea/argument/FieldTest.java b/app/src/test/java/org/astraea/app/argument/FieldTest.java
similarity index 94%
rename from app/src/test/java/org/astraea/argument/FieldTest.java
rename to app/src/test/java/org/astraea/app/argument/FieldTest.java
index c4cd2868..fb2c832e 100644
--- a/app/src/test/java/org/astraea/argument/FieldTest.java
+++ b/app/src/test/java/org/astraea/app/argument/FieldTest.java
@@ -1,4 +1,4 @@
-package org.astraea.argument;
+package org.astraea.app.argument;
 
 import com.beust.jcommander.ParameterException;
 import org.junit.jupiter.api.Assertions;
diff --git a/app/src/test/java/org/astraea/argument/NonNegativeFieldTest.java b/app/src/test/java/org/astraea/app/argument/NonNegativeFieldTest.java
similarity index 65%
rename from app/src/test/java/org/astraea/argument/NonNegativeFieldTest.java
rename to app/src/test/java/org/astraea/app/argument/NonNegativeFieldTest.java
index 5ef681d1..99498925 100644
--- a/app/src/test/java/org/astraea/argument/NonNegativeFieldTest.java
+++ b/app/src/test/java/org/astraea/app/argument/NonNegativeFieldTest.java
@@ -1,4 +1,4 @@
-package org.astraea.argument;
+package org.astraea.app.argument;
 
 import com.beust.jcommander.Parameter;
 import com.beust.jcommander.ParameterException;
@@ -16,14 +16,11 @@ public class NonNegativeFieldTest {
 
   @Test
   public void testNotNegative() {
-    var param =
-        org.astraea.argument.Argument.parse(new FakeParameter(), new String[] {"--field", "1000"});
+    var param = Argument.parse(new FakeParameter(), new String[] {"--field", "1000"});
 
     Assertions.assertEquals(1000, param.value);
     Assertions.assertThrows(
         ParameterException.class,
-        () ->
-            org.astraea.argument.Argument.parse(
-                new FakeParameter(), new String[] {"--field", "-1"}));
+        () -> Argument.parse(new FakeParameter(), new String[] {"--field", "-1"}));
   }
 }
diff --git a/app/src/test/java/org/astraea/argument/PositiveFieldTest.java b/app/src/test/java/org/astraea/app/argument/PositiveFieldTest.java
similarity index 58%
rename from app/src/test/java/org/astraea/argument/PositiveFieldTest.java
rename to app/src/test/java/org/astraea/app/argument/PositiveFieldTest.java
index 9408d02b..0794f4c2 100644
--- a/app/src/test/java/org/astraea/argument/PositiveFieldTest.java
+++ b/app/src/test/java/org/astraea/app/argument/PositiveFieldTest.java
@@ -1,4 +1,4 @@
-package org.astraea.argument;
+package org.astraea.app.argument;
 
 import com.beust.jcommander.Parameter;
 import com.beust.jcommander.ParameterException;
@@ -16,19 +16,14 @@ public class PositiveFieldTest {
 
   @Test
   public void testNotNegative() {
-    var param =
-        org.astraea.argument.Argument.parse(new FakeParameter(), new String[] {"--field", "1000"});
+    var param = Argument.parse(new FakeParameter(), new String[] {"--field", "1000"});
 
     Assertions.assertEquals(1000, param.value);
     Assertions.assertThrows(
         ParameterException.class,
-        () ->
-            org.astraea.argument.Argument.parse(
-                new FakeParameter(), new String[] {"--field", "0"}));
+        () -> Argument.parse(new FakeParameter(), new String[] {"--field", "0"}));
     Assertions.assertThrows(
         ParameterException.class,
-        () ->
-            org.astraea.argument.Argument.parse(
-                new FakeParameter(), new String[] {"--field", "-1"}));
+        () -> Argument.parse(new FakeParameter(), new String[] {"--field", "-1"}));
   }
 }
diff --git a/app/src/test/java/org/astraea/argument/SetFieldTest.java b/app/src/test/java/org/astraea/app/argument/SetFieldTest.java
similarity index 76%
rename from app/src/test/java/org/astraea/argument/SetFieldTest.java
rename to app/src/test/java/org/astraea/app/argument/SetFieldTest.java
index 911719a7..40049682 100644
--- a/app/src/test/java/org/astraea/argument/SetFieldTest.java
+++ b/app/src/test/java/org/astraea/app/argument/SetFieldTest.java
@@ -1,4 +1,4 @@
-package org.astraea.argument;
+package org.astraea.app.argument;
 
 import com.beust.jcommander.Parameter;
 import java.util.Set;
@@ -16,8 +16,7 @@ public class SetFieldTest {
 
   @Test
   public void testSetConverter() {
-    var param =
-        org.astraea.argument.Argument.parse(new FakeParameter(), new String[] {"--field", "1,2,3"});
+    var param = Argument.parse(new FakeParameter(), new String[] {"--field", "1,2,3"});
 
     Assertions.assertEquals(Set.of("1", "2", "3"), param.value);
   }
diff --git a/app/src/test/java/org/astraea/argument/StringMapFieldTest.java b/app/src/test/java/org/astraea/app/argument/StringMapFieldTest.java
similarity index 95%
rename from app/src/test/java/org/astraea/argument/StringMapFieldTest.java
rename to app/src/test/java/org/astraea/app/argument/StringMapFieldTest.java
index e92e5c15..f5e4c9f4 100644
--- a/app/src/test/java/org/astraea/argument/StringMapFieldTest.java
+++ b/app/src/test/java/org/astraea/app/argument/StringMapFieldTest.java
@@ -1,4 +1,4 @@
-package org.astraea.argument;
+package org.astraea.app.argument;
 
 import com.beust.jcommander.ParameterException;
 import org.junit.jupiter.api.Assertions;
diff --git a/app/src/test/java/org/astraea/balancer/RebalancePlanProposalTest.java b/app/src/test/java/org/astraea/app/balancer/RebalancePlanProposalTest.java
similarity index 94%
rename from app/src/test/java/org/astraea/balancer/RebalancePlanProposalTest.java
rename to app/src/test/java/org/astraea/app/balancer/RebalancePlanProposalTest.java
index 89c28eb7..ba4030ec 100644
--- a/app/src/test/java/org/astraea/balancer/RebalancePlanProposalTest.java
+++ b/app/src/test/java/org/astraea/app/balancer/RebalancePlanProposalTest.java
@@ -1,8 +1,8 @@
-package org.astraea.balancer;
+package org.astraea.app.balancer;
 
 import java.util.stream.Collectors;
-import org.astraea.balancer.log.LayeredClusterLogAllocation;
-import org.astraea.cost.ClusterInfoProvider;
+import org.astraea.app.balancer.log.LayeredClusterLogAllocation;
+import org.astraea.app.cost.ClusterInfoProvider;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
diff --git a/app/src/test/java/org/astraea/balancer/generator/ShufflePlanGeneratorTest.java b/app/src/test/java/org/astraea/app/balancer/generator/ShufflePlanGeneratorTest.java
similarity index 97%
rename from app/src/test/java/org/astraea/balancer/generator/ShufflePlanGeneratorTest.java
rename to app/src/test/java/org/astraea/app/balancer/generator/ShufflePlanGeneratorTest.java
index e6dac26e..d3f7c570 100644
--- a/app/src/test/java/org/astraea/balancer/generator/ShufflePlanGeneratorTest.java
+++ b/app/src/test/java/org/astraea/app/balancer/generator/ShufflePlanGeneratorTest.java
@@ -1,11 +1,11 @@
-package org.astraea.balancer.generator;
+package org.astraea.app.balancer.generator;
 
 import java.util.concurrent.ForkJoinPool;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.LongAdder;
 import java.util.stream.Collectors;
-import org.astraea.balancer.log.LayeredClusterLogAllocation;
-import org.astraea.cost.ClusterInfoProvider;
+import org.astraea.app.balancer.log.LayeredClusterLogAllocation;
+import org.astraea.app.cost.ClusterInfoProvider;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
diff --git a/app/src/test/java/org/astraea/balancer/log/LayeredClusterLogAllocationTest.java b/app/src/test/java/org/astraea/app/balancer/log/LayeredClusterLogAllocationTest.java
similarity index 98%
rename from app/src/test/java/org/astraea/balancer/log/LayeredClusterLogAllocationTest.java
rename to app/src/test/java/org/astraea/app/balancer/log/LayeredClusterLogAllocationTest.java
index 32427f7d..7f54dd7d 100644
--- a/app/src/test/java/org/astraea/balancer/log/LayeredClusterLogAllocationTest.java
+++ b/app/src/test/java/org/astraea/app/balancer/log/LayeredClusterLogAllocationTest.java
@@ -1,12 +1,12 @@
-package org.astraea.balancer.log;
+package org.astraea.app.balancer.log;
 
 import java.util.Comparator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.stream.Collectors;
-import org.astraea.admin.TopicPartition;
-import org.astraea.cost.ClusterInfoProvider;
+import org.astraea.app.admin.TopicPartition;
+import org.astraea.app.cost.ClusterInfoProvider;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
diff --git a/app/src/test/java/org/astraea/common/DataRateTest.java b/app/src/test/java/org/astraea/app/common/DataRateTest.java
similarity index 99%
rename from app/src/test/java/org/astraea/common/DataRateTest.java
rename to app/src/test/java/org/astraea/app/common/DataRateTest.java
index 050dd571..2e5f560d 100644
--- a/app/src/test/java/org/astraea/common/DataRateTest.java
+++ b/app/src/test/java/org/astraea/app/common/DataRateTest.java
@@ -1,4 +1,4 @@
-package org.astraea.common;
+package org.astraea.app.common;
 
 import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
 import static org.junit.jupiter.api.Assertions.assertEquals;
diff --git a/app/src/test/java/org/astraea/common/DataSizeTest.java b/app/src/test/java/org/astraea/app/common/DataSizeTest.java
similarity index 99%
rename from app/src/test/java/org/astraea/common/DataSizeTest.java
rename to app/src/test/java/org/astraea/app/common/DataSizeTest.java
index 4e18039f..6b624f66 100644
--- a/app/src/test/java/org/astraea/common/DataSizeTest.java
+++ b/app/src/test/java/org/astraea/app/common/DataSizeTest.java
@@ -1,4 +1,4 @@
-package org.astraea.common;
+package org.astraea.app.common;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
diff --git a/app/src/test/java/org/astraea/common/UtilsTest.java b/app/src/test/java/org/astraea/app/common/UtilsTest.java
similarity index 97%
rename from app/src/test/java/org/astraea/common/UtilsTest.java
rename to app/src/test/java/org/astraea/app/common/UtilsTest.java
index de6a7447..69a0e474 100644
--- a/app/src/test/java/org/astraea/common/UtilsTest.java
+++ b/app/src/test/java/org/astraea/app/common/UtilsTest.java
@@ -1,4 +1,4 @@
-package org.astraea.common;
+package org.astraea.app.common;
 
 import java.io.IOException;
 import java.util.Map;
diff --git a/app/src/test/java/org/astraea/concurrent/ThreadPoolTest.java b/app/src/test/java/org/astraea/app/concurrent/ThreadPoolTest.java
similarity index 98%
rename from app/src/test/java/org/astraea/concurrent/ThreadPoolTest.java
rename to app/src/test/java/org/astraea/app/concurrent/ThreadPoolTest.java
index 6548137d..8ecbd3e4 100644
--- a/app/src/test/java/org/astraea/concurrent/ThreadPoolTest.java
+++ b/app/src/test/java/org/astraea/app/concurrent/ThreadPoolTest.java
@@ -1,4 +1,4 @@
-package org.astraea.concurrent;
+package org.astraea.app.concurrent;
 
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
diff --git a/app/src/test/java/org/astraea/consumer/ConsumerTest.java b/app/src/test/java/org/astraea/app/consumer/ConsumerTest.java
similarity index 96%
rename from app/src/test/java/org/astraea/consumer/ConsumerTest.java
rename to app/src/test/java/org/astraea/app/consumer/ConsumerTest.java
index 1848e480..6062837d 100644
--- a/app/src/test/java/org/astraea/consumer/ConsumerTest.java
+++ b/app/src/test/java/org/astraea/app/consumer/ConsumerTest.java
@@ -1,4 +1,4 @@
-package org.astraea.consumer;
+package org.astraea.app.consumer;
 
 import java.nio.charset.StandardCharsets;
 import java.time.Duration;
@@ -7,9 +7,9 @@ import java.util.concurrent.Executors;
 import java.util.concurrent.TimeUnit;
 import java.util.stream.IntStream;
 import org.apache.kafka.common.errors.WakeupException;
-import org.astraea.common.Utils;
-import org.astraea.producer.Producer;
-import org.astraea.service.RequireBrokerCluster;
+import org.astraea.app.common.Utils;
+import org.astraea.app.producer.Producer;
+import org.astraea.app.service.RequireBrokerCluster;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.Timeout;
diff --git a/app/src/test/java/org/astraea/consumer/RebalanceListenerTest.java b/app/src/test/java/org/astraea/app/consumer/RebalanceListenerTest.java
similarity index 82%
rename from app/src/test/java/org/astraea/consumer/RebalanceListenerTest.java
rename to app/src/test/java/org/astraea/app/consumer/RebalanceListenerTest.java
index 49d92866..68b5ca00 100644
--- a/app/src/test/java/org/astraea/consumer/RebalanceListenerTest.java
+++ b/app/src/test/java/org/astraea/app/consumer/RebalanceListenerTest.java
@@ -1,12 +1,12 @@
-package org.astraea.consumer;
+package org.astraea.app.consumer;
 
 import java.time.Duration;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicInteger;
-import org.astraea.common.Utils;
-import org.astraea.concurrent.State;
-import org.astraea.concurrent.ThreadPool;
-import org.astraea.service.RequireBrokerCluster;
+import org.astraea.app.common.Utils;
+import org.astraea.app.concurrent.State;
+import org.astraea.app.concurrent.ThreadPool;
+import org.astraea.app.service.RequireBrokerCluster;
 import org.junit.jupiter.api.Test;
 
 public class RebalanceListenerTest extends RequireBrokerCluster {
diff --git a/app/src/test/java/org/astraea/cost/ClusterInfoProvider.java b/app/src/test/java/org/astraea/app/cost/ClusterInfoProvider.java
similarity index 96%
rename from app/src/test/java/org/astraea/cost/ClusterInfoProvider.java
rename to app/src/test/java/org/astraea/app/cost/ClusterInfoProvider.java
index f69926b9..0b66cb0c 100644
--- a/app/src/test/java/org/astraea/cost/ClusterInfoProvider.java
+++ b/app/src/test/java/org/astraea/app/cost/ClusterInfoProvider.java
@@ -1,4 +1,4 @@
-package org.astraea.cost;
+package org.astraea.app.cost;
 
 import java.util.Collection;
 import java.util.List;
@@ -8,8 +8,8 @@ import java.util.Set;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
-import org.astraea.admin.TopicPartition;
-import org.astraea.metrics.HasBeanObject;
+import org.astraea.app.admin.TopicPartition;
+import org.astraea.app.metrics.HasBeanObject;
 
 public class ClusterInfoProvider {
 
diff --git a/app/src/test/java/org/astraea/cost/ClusterInfoTest.java b/app/src/test/java/org/astraea/app/cost/ClusterInfoTest.java
similarity index 96%
rename from app/src/test/java/org/astraea/cost/ClusterInfoTest.java
rename to app/src/test/java/org/astraea/app/cost/ClusterInfoTest.java
index 26fabe9d..0227ce77 100644
--- a/app/src/test/java/org/astraea/cost/ClusterInfoTest.java
+++ b/app/src/test/java/org/astraea/app/cost/ClusterInfoTest.java
@@ -1,10 +1,10 @@
-package org.astraea.cost;
+package org.astraea.app.cost;
 
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 import org.apache.kafka.common.Cluster;
-import org.astraea.metrics.HasBeanObject;
+import org.astraea.app.metrics.HasBeanObject;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 import org.mockito.Mockito;
diff --git a/app/src/test/java/org/astraea/cost/FakeClusterInfo.java b/app/src/test/java/org/astraea/app/cost/FakeClusterInfo.java
similarity index 92%
rename from app/src/test/java/org/astraea/cost/FakeClusterInfo.java
rename to app/src/test/java/org/astraea/app/cost/FakeClusterInfo.java
index 0a2e71e1..f27a8c0d 100644
--- a/app/src/test/java/org/astraea/cost/FakeClusterInfo.java
+++ b/app/src/test/java/org/astraea/app/cost/FakeClusterInfo.java
@@ -1,10 +1,10 @@
-package org.astraea.cost;
+package org.astraea.app.cost;
 
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import org.astraea.metrics.HasBeanObject;
+import org.astraea.app.metrics.HasBeanObject;
 
 public class FakeClusterInfo implements ClusterInfo {
   @Override
diff --git a/app/src/test/java/org/astraea/cost/LoadCostTest.java b/app/src/test/java/org/astraea/app/cost/LoadCostTest.java
similarity index 90%
rename from app/src/test/java/org/astraea/cost/LoadCostTest.java
rename to app/src/test/java/org/astraea/app/cost/LoadCostTest.java
index e520b208..3c4835f6 100644
--- a/app/src/test/java/org/astraea/cost/LoadCostTest.java
+++ b/app/src/test/java/org/astraea/app/cost/LoadCostTest.java
@@ -1,12 +1,12 @@
-package org.astraea.cost;
+package org.astraea.app.cost;
 
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
-import org.astraea.metrics.HasBeanObject;
-import org.astraea.metrics.jmx.BeanObject;
-import org.astraea.metrics.kafka.BrokerTopicMetricsResult;
-import org.astraea.metrics.kafka.KafkaMetrics;
+import org.astraea.app.metrics.HasBeanObject;
+import org.astraea.app.metrics.jmx.BeanObject;
+import org.astraea.app.metrics.kafka.BrokerTopicMetricsResult;
+import org.astraea.app.metrics.kafka.KafkaMetrics;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 import org.mockito.Mockito;
diff --git a/app/src/test/java/org/astraea/cost/NodeInfoTest.java b/app/src/test/java/org/astraea/app/cost/NodeInfoTest.java
similarity index 94%
rename from app/src/test/java/org/astraea/cost/NodeInfoTest.java
rename to app/src/test/java/org/astraea/app/cost/NodeInfoTest.java
index 61b6434e..ef8ca921 100644
--- a/app/src/test/java/org/astraea/cost/NodeInfoTest.java
+++ b/app/src/test/java/org/astraea/app/cost/NodeInfoTest.java
@@ -1,4 +1,4 @@
-package org.astraea.cost;
+package org.astraea.app.cost;
 
 import org.apache.kafka.common.Node;
 import org.junit.jupiter.api.Assertions;
diff --git a/app/src/test/java/org/astraea/cost/NormalizerTest.java b/app/src/test/java/org/astraea/app/cost/NormalizerTest.java
similarity index 98%
rename from app/src/test/java/org/astraea/cost/NormalizerTest.java
rename to app/src/test/java/org/astraea/app/cost/NormalizerTest.java
index cefa960f..55386c25 100644
--- a/app/src/test/java/org/astraea/cost/NormalizerTest.java
+++ b/app/src/test/java/org/astraea/app/cost/NormalizerTest.java
@@ -1,4 +1,4 @@
-package org.astraea.cost;
+package org.astraea.app.cost;
 
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
diff --git a/app/src/test/java/org/astraea/cost/PeriodicTest.java b/app/src/test/java/org/astraea/app/cost/PeriodicTest.java
similarity index 97%
rename from app/src/test/java/org/astraea/cost/PeriodicTest.java
rename to app/src/test/java/org/astraea/app/cost/PeriodicTest.java
index f071e4db..cf64b685 100644
--- a/app/src/test/java/org/astraea/cost/PeriodicTest.java
+++ b/app/src/test/java/org/astraea/app/cost/PeriodicTest.java
@@ -1,4 +1,4 @@
-package org.astraea.cost;
+package org.astraea.app.cost;
 
 import java.time.Duration;
 import java.util.HashMap;
diff --git a/app/src/test/java/org/astraea/cost/ReplicaInfoTest.java b/app/src/test/java/org/astraea/app/cost/ReplicaInfoTest.java
similarity index 98%
rename from app/src/test/java/org/astraea/cost/ReplicaInfoTest.java
rename to app/src/test/java/org/astraea/app/cost/ReplicaInfoTest.java
index eb92b69c..406d074b 100644
--- a/app/src/test/java/org/astraea/cost/ReplicaInfoTest.java
+++ b/app/src/test/java/org/astraea/app/cost/ReplicaInfoTest.java
@@ -1,4 +1,4 @@
-package org.astraea.cost;
+package org.astraea.app.cost;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/app/src/test/java/org/astraea/cost/ThroughputCostTest.java b/app/src/test/java/org/astraea/app/cost/ThroughputCostTest.java
similarity index 93%
rename from app/src/test/java/org/astraea/cost/ThroughputCostTest.java
rename to app/src/test/java/org/astraea/app/cost/ThroughputCostTest.java
index 580ae0f1..ebe3711b 100644
--- a/app/src/test/java/org/astraea/cost/ThroughputCostTest.java
+++ b/app/src/test/java/org/astraea/app/cost/ThroughputCostTest.java
@@ -1,9 +1,9 @@
-package org.astraea.cost;
+package org.astraea.app.cost;
 
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import org.astraea.metrics.kafka.BrokerTopicMetricsResult;
+import org.astraea.app.metrics.kafka.BrokerTopicMetricsResult;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 import org.mockito.Mockito;
diff --git a/app/src/test/java/org/astraea/cost/WeightProviderTest.java b/app/src/test/java/org/astraea/app/cost/WeightProviderTest.java
similarity index 98%
rename from app/src/test/java/org/astraea/cost/WeightProviderTest.java
rename to app/src/test/java/org/astraea/app/cost/WeightProviderTest.java
index c72080b5..fed38cc2 100644
--- a/app/src/test/java/org/astraea/cost/WeightProviderTest.java
+++ b/app/src/test/java/org/astraea/app/cost/WeightProviderTest.java
@@ -1,4 +1,4 @@
-package org.astraea.cost;
+package org.astraea.app.cost;
 
 import java.util.Comparator;
 import java.util.Map;
diff --git a/app/src/test/java/org/astraea/cost/broker/BrokerInputCostTest.java b/app/src/test/java/org/astraea/app/cost/broker/BrokerInputCostTest.java
similarity index 85%
rename from app/src/test/java/org/astraea/cost/broker/BrokerInputCostTest.java
rename to app/src/test/java/org/astraea/app/cost/broker/BrokerInputCostTest.java
index 8302b4ae..c158d147 100644
--- a/app/src/test/java/org/astraea/cost/broker/BrokerInputCostTest.java
+++ b/app/src/test/java/org/astraea/app/cost/broker/BrokerInputCostTest.java
@@ -1,14 +1,14 @@
-package org.astraea.cost.broker;
+package org.astraea.app.cost.broker;
 
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
-import org.astraea.cost.ClusterInfo;
-import org.astraea.cost.FakeClusterInfo;
-import org.astraea.metrics.HasBeanObject;
-import org.astraea.metrics.jmx.BeanObject;
-import org.astraea.metrics.kafka.BrokerTopicMetricsResult;
-import org.astraea.metrics.kafka.KafkaMetrics;
+import org.astraea.app.cost.ClusterInfo;
+import org.astraea.app.cost.FakeClusterInfo;
+import org.astraea.app.metrics.HasBeanObject;
+import org.astraea.app.metrics.jmx.BeanObject;
+import org.astraea.app.metrics.kafka.BrokerTopicMetricsResult;
+import org.astraea.app.metrics.kafka.KafkaMetrics;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 import org.mockito.Mockito;
diff --git a/app/src/test/java/org/astraea/cost/broker/BrokerOutPutCostTest.java b/app/src/test/java/org/astraea/app/cost/broker/BrokerOutPutCostTest.java
similarity index 86%
rename from app/src/test/java/org/astraea/cost/broker/BrokerOutPutCostTest.java
rename to app/src/test/java/org/astraea/app/cost/broker/BrokerOutPutCostTest.java
index 7f666090..11d44488 100644
--- a/app/src/test/java/org/astraea/cost/broker/BrokerOutPutCostTest.java
+++ b/app/src/test/java/org/astraea/app/cost/broker/BrokerOutPutCostTest.java
@@ -1,14 +1,14 @@
-package org.astraea.cost.broker;
+package org.astraea.app.cost.broker;
 
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
-import org.astraea.cost.ClusterInfo;
-import org.astraea.cost.FakeClusterInfo;
-import org.astraea.metrics.HasBeanObject;
-import org.astraea.metrics.jmx.BeanObject;
-import org.astraea.metrics.kafka.BrokerTopicMetricsResult;
-import org.astraea.metrics.kafka.KafkaMetrics;
+import org.astraea.app.cost.ClusterInfo;
+import org.astraea.app.cost.FakeClusterInfo;
+import org.astraea.app.metrics.HasBeanObject;
+import org.astraea.app.metrics.jmx.BeanObject;
+import org.astraea.app.metrics.kafka.BrokerTopicMetricsResult;
+import org.astraea.app.metrics.kafka.KafkaMetrics;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 import org.mockito.Mockito;
diff --git a/app/src/test/java/org/astraea/cost/broker/CpuCostTest.java b/app/src/test/java/org/astraea/app/cost/broker/CpuCostTest.java
similarity index 90%
rename from app/src/test/java/org/astraea/cost/broker/CpuCostTest.java
rename to app/src/test/java/org/astraea/app/cost/broker/CpuCostTest.java
index 516501d3..e90ce4ce 100644
--- a/app/src/test/java/org/astraea/cost/broker/CpuCostTest.java
+++ b/app/src/test/java/org/astraea/app/cost/broker/CpuCostTest.java
@@ -1,15 +1,15 @@
-package org.astraea.cost.broker;
+package org.astraea.app.cost.broker;
 
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import org.astraea.cost.ClusterInfo;
-import org.astraea.cost.FakeClusterInfo;
-import org.astraea.cost.NodeInfo;
-import org.astraea.cost.ReplicaInfo;
-import org.astraea.metrics.HasBeanObject;
-import org.astraea.metrics.java.OperatingSystemInfo;
+import org.astraea.app.cost.ClusterInfo;
+import org.astraea.app.cost.FakeClusterInfo;
+import org.astraea.app.cost.NodeInfo;
+import org.astraea.app.cost.ReplicaInfo;
+import org.astraea.app.metrics.HasBeanObject;
+import org.astraea.app.metrics.java.OperatingSystemInfo;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 import org.mockito.Mockito;
diff --git a/app/src/test/java/org/astraea/cost/broker/MemoryCostTest.java b/app/src/test/java/org/astraea/app/cost/broker/MemoryCostTest.java
similarity index 91%
rename from app/src/test/java/org/astraea/cost/broker/MemoryCostTest.java
rename to app/src/test/java/org/astraea/app/cost/broker/MemoryCostTest.java
index 434d15be..6497e4bd 100644
--- a/app/src/test/java/org/astraea/cost/broker/MemoryCostTest.java
+++ b/app/src/test/java/org/astraea/app/cost/broker/MemoryCostTest.java
@@ -1,16 +1,16 @@
-package org.astraea.cost.broker;
+package org.astraea.app.cost.broker;
 
 import java.lang.management.MemoryUsage;
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import org.astraea.cost.ClusterInfo;
-import org.astraea.cost.FakeClusterInfo;
-import org.astraea.cost.NodeInfo;
-import org.astraea.cost.ReplicaInfo;
-import org.astraea.metrics.HasBeanObject;
-import org.astraea.metrics.java.HasJvmMemory;
+import org.astraea.app.cost.ClusterInfo;
+import org.astraea.app.cost.FakeClusterInfo;
+import org.astraea.app.cost.NodeInfo;
+import org.astraea.app.cost.ReplicaInfo;
+import org.astraea.app.metrics.HasBeanObject;
+import org.astraea.app.metrics.java.HasJvmMemory;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 import org.mockito.Mockito;
diff --git a/app/src/test/java/org/astraea/cost/topic/CalculateUtilsTest.java b/app/src/test/java/org/astraea/app/cost/topic/CalculateUtilsTest.java
similarity index 98%
rename from app/src/test/java/org/astraea/cost/topic/CalculateUtilsTest.java
rename to app/src/test/java/org/astraea/app/cost/topic/CalculateUtilsTest.java
index 2f7b30e7..f482ad36 100644
--- a/app/src/test/java/org/astraea/cost/topic/CalculateUtilsTest.java
+++ b/app/src/test/java/org/astraea/app/cost/topic/CalculateUtilsTest.java
@@ -1,10 +1,10 @@
-package org.astraea.cost.topic;
+package org.astraea.app.cost.topic;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
 import java.util.HashMap;
 import java.util.Map;
-import org.astraea.admin.TopicPartition;
+import org.astraea.app.admin.TopicPartition;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
 
diff --git a/app/src/test/java/org/astraea/cost/topic/GetPartitionInfTest.java b/app/src/test/java/org/astraea/app/cost/topic/GetPartitionInfTest.java
similarity index 91%
rename from app/src/test/java/org/astraea/cost/topic/GetPartitionInfTest.java
rename to app/src/test/java/org/astraea/app/cost/topic/GetPartitionInfTest.java
index 4eb590af..324f549d 100644
--- a/app/src/test/java/org/astraea/cost/topic/GetPartitionInfTest.java
+++ b/app/src/test/java/org/astraea/app/cost/topic/GetPartitionInfTest.java
@@ -1,4 +1,4 @@
-package org.astraea.cost.topic;
+package org.astraea.app.cost.topic;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
@@ -6,10 +6,10 @@ import java.util.HashMap;
 import java.util.Map;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
-import org.astraea.admin.Admin;
-import org.astraea.producer.Producer;
-import org.astraea.producer.Serializer;
-import org.astraea.service.RequireBrokerCluster;
+import org.astraea.app.admin.Admin;
+import org.astraea.app.producer.Producer;
+import org.astraea.app.producer.Serializer;
+import org.astraea.app.service.RequireBrokerCluster;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
 
diff --git a/app/src/test/java/org/astraea/cost/topic/PartitionScoreTest.java b/app/src/test/java/org/astraea/app/cost/topic/PartitionScoreTest.java
similarity index 91%
rename from app/src/test/java/org/astraea/cost/topic/PartitionScoreTest.java
rename to app/src/test/java/org/astraea/app/cost/topic/PartitionScoreTest.java
index 3c592247..6cf81680 100644
--- a/app/src/test/java/org/astraea/cost/topic/PartitionScoreTest.java
+++ b/app/src/test/java/org/astraea/app/cost/topic/PartitionScoreTest.java
@@ -1,4 +1,4 @@
-package org.astraea.cost.topic;
+package org.astraea.app.cost.topic;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
@@ -6,10 +6,10 @@ import java.util.HashMap;
 import java.util.Map;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
-import org.astraea.admin.Admin;
-import org.astraea.producer.Producer;
-import org.astraea.producer.Serializer;
-import org.astraea.service.RequireBrokerCluster;
+import org.astraea.app.admin.Admin;
+import org.astraea.app.producer.Producer;
+import org.astraea.app.producer.Serializer;
+import org.astraea.app.service.RequireBrokerCluster;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
 
diff --git a/app/src/test/java/org/astraea/database/DatabaseClientTest.java b/app/src/test/java/org/astraea/app/database/DatabaseClientTest.java
similarity index 96%
rename from app/src/test/java/org/astraea/database/DatabaseClientTest.java
rename to app/src/test/java/org/astraea/app/database/DatabaseClientTest.java
index 8c61e96e..485a3019 100644
--- a/app/src/test/java/org/astraea/database/DatabaseClientTest.java
+++ b/app/src/test/java/org/astraea/app/database/DatabaseClientTest.java
@@ -1,7 +1,7 @@
-package org.astraea.database;
+package org.astraea.app.database;
 
-import org.astraea.common.Utils;
-import org.astraea.service.Database;
+import org.astraea.app.common.Utils;
+import org.astraea.app.service.Database;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
diff --git a/app/src/test/java/org/astraea/metrics/MetricExplorerTest.java b/app/src/test/java/org/astraea/app/metrics/MetricExplorerTest.java
similarity index 89%
rename from app/src/test/java/org/astraea/metrics/MetricExplorerTest.java
rename to app/src/test/java/org/astraea/app/metrics/MetricExplorerTest.java
index 1939854b..f50b9e8c 100644
--- a/app/src/test/java/org/astraea/metrics/MetricExplorerTest.java
+++ b/app/src/test/java/org/astraea/app/metrics/MetricExplorerTest.java
@@ -1,6 +1,5 @@
-package org.astraea.metrics;
+package org.astraea.app.metrics;
 
-import static org.astraea.metrics.MetricExplorer.Argument;
 import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertThrows;
@@ -15,8 +14,9 @@ import java.util.List;
 import java.util.Map;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
-import org.astraea.metrics.jmx.BeanObject;
-import org.astraea.metrics.jmx.MBeanClient;
+import org.astraea.app.argument.Argument;
+import org.astraea.app.metrics.jmx.BeanObject;
+import org.astraea.app.metrics.jmx.MBeanClient;
 import org.junit.jupiter.api.function.Executable;
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.CsvSource;
@@ -37,7 +37,7 @@ class MetricExplorerTest {
       })
   void testPatternJmxUrlStart(String url, String expected) {
     // arrange
-    Pattern pattern = Argument.JmxServerUrlField.patternOfJmxUrlStart;
+    Pattern pattern = MetricExplorer.Argument.JmxServerUrlField.patternOfJmxUrlStart;
 
     // act
     Matcher matcher = pattern.matcher(url);
@@ -58,7 +58,7 @@ class MetricExplorerTest {
       })
   void testPatternProperty(String property, String key, String value) {
     // arrange
-    Pattern pattern = Argument.CorrectPropertyFormat.propertyPattern;
+    Pattern pattern = MetricExplorer.Argument.CorrectPropertyFormat.propertyPattern;
 
     // act
     Matcher matcher = pattern.matcher(property);
@@ -77,7 +77,7 @@ class MetricExplorerTest {
       })
   void executeDoesPrintSomething(String args) {
     // arrange
-    var argument = org.astraea.argument.Argument.parse(new Argument(), args.split(" "));
+    var argument = Argument.parse(new MetricExplorer.Argument(), args.split(" "));
     var mockMBeanClient = mock(MBeanClient.class);
     when(mockMBeanClient.queryBeans(any()))
         .thenReturn(List.of(new BeanObject("example.com", Map.of("key", "value"), Map.of())));
@@ -115,7 +115,7 @@ class MetricExplorerTest {
     String[] arguments = argumentString.split(" ");
 
     // act
-    Executable doParsing = () -> org.astraea.argument.Argument.parse(new Argument(), arguments);
+    Executable doParsing = () -> Argument.parse(new MetricExplorer.Argument(), arguments);
 
     // assert
     if (outcome.equals("ok")) {
diff --git a/app/src/test/java/org/astraea/metrics/collector/BeanCollectorTest.java b/app/src/test/java/org/astraea/app/metrics/collector/BeanCollectorTest.java
similarity index 96%
rename from app/src/test/java/org/astraea/metrics/collector/BeanCollectorTest.java
rename to app/src/test/java/org/astraea/app/metrics/collector/BeanCollectorTest.java
index 06d74bf6..a8d0d5ae 100644
--- a/app/src/test/java/org/astraea/metrics/collector/BeanCollectorTest.java
+++ b/app/src/test/java/org/astraea/app/metrics/collector/BeanCollectorTest.java
@@ -1,4 +1,4 @@
-package org.astraea.metrics.collector;
+package org.astraea.app.metrics.collector;
 
 import java.time.Duration;
 import java.util.ArrayList;
@@ -9,12 +9,12 @@ import java.util.concurrent.atomic.AtomicInteger;
 import java.util.function.BiFunction;
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
-import org.astraea.concurrent.Executor;
-import org.astraea.concurrent.State;
-import org.astraea.concurrent.ThreadPool;
-import org.astraea.metrics.HasBeanObject;
-import org.astraea.metrics.jmx.BeanObject;
-import org.astraea.metrics.jmx.MBeanClient;
+import org.astraea.app.concurrent.Executor;
+import org.astraea.app.concurrent.State;
+import org.astraea.app.concurrent.ThreadPool;
+import org.astraea.app.metrics.HasBeanObject;
+import org.astraea.app.metrics.jmx.BeanObject;
+import org.astraea.app.metrics.jmx.MBeanClient;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 import org.mockito.Mockito;
diff --git a/app/src/test/java/org/astraea/metrics/collector/FetcherTest.java b/app/src/test/java/org/astraea/app/metrics/collector/FetcherTest.java
similarity index 83%
rename from app/src/test/java/org/astraea/metrics/collector/FetcherTest.java
rename to app/src/test/java/org/astraea/app/metrics/collector/FetcherTest.java
index 74383c17..881e4052 100644
--- a/app/src/test/java/org/astraea/metrics/collector/FetcherTest.java
+++ b/app/src/test/java/org/astraea/app/metrics/collector/FetcherTest.java
@@ -1,8 +1,8 @@
-package org.astraea.metrics.collector;
+package org.astraea.app.metrics.collector;
 
 import java.util.List;
-import org.astraea.metrics.HasBeanObject;
-import org.astraea.metrics.jmx.MBeanClient;
+import org.astraea.app.metrics.HasBeanObject;
+import org.astraea.app.metrics.jmx.MBeanClient;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 import org.mockito.Mockito;
diff --git a/app/src/test/java/org/astraea/metrics/jmx/BeanObjectTest.java b/app/src/test/java/org/astraea/app/metrics/jmx/BeanObjectTest.java
similarity index 96%
rename from app/src/test/java/org/astraea/metrics/jmx/BeanObjectTest.java
rename to app/src/test/java/org/astraea/app/metrics/jmx/BeanObjectTest.java
index 1bde9b1a..aac38b7e 100644
--- a/app/src/test/java/org/astraea/metrics/jmx/BeanObjectTest.java
+++ b/app/src/test/java/org/astraea/app/metrics/jmx/BeanObjectTest.java
@@ -1,4 +1,4 @@
-package org.astraea.metrics.jmx;
+package org.astraea.app.metrics.jmx;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertTrue;
diff --git a/app/src/test/java/org/astraea/metrics/jmx/BeanQueryTest.java b/app/src/test/java/org/astraea/app/metrics/jmx/BeanQueryTest.java
similarity index 98%
rename from app/src/test/java/org/astraea/metrics/jmx/BeanQueryTest.java
rename to app/src/test/java/org/astraea/app/metrics/jmx/BeanQueryTest.java
index 7ed80264..3e2d9060 100644
--- a/app/src/test/java/org/astraea/metrics/jmx/BeanQueryTest.java
+++ b/app/src/test/java/org/astraea/app/metrics/jmx/BeanQueryTest.java
@@ -1,4 +1,4 @@
-package org.astraea.metrics.jmx;
+package org.astraea.app.metrics.jmx;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
diff --git a/app/src/test/java/org/astraea/metrics/jmx/MBeanClientTest.java b/app/src/test/java/org/astraea/app/metrics/jmx/MBeanClientTest.java
similarity index 99%
rename from app/src/test/java/org/astraea/metrics/jmx/MBeanClientTest.java
rename to app/src/test/java/org/astraea/app/metrics/jmx/MBeanClientTest.java
index 512eb756..916cf49b 100644
--- a/app/src/test/java/org/astraea/metrics/jmx/MBeanClientTest.java
+++ b/app/src/test/java/org/astraea/app/metrics/jmx/MBeanClientTest.java
@@ -1,4 +1,4 @@
-package org.astraea.metrics.jmx;
+package org.astraea.app.metrics.jmx;
 
 import static java.util.stream.Collectors.toList;
 import static java.util.stream.Collectors.toMap;
diff --git a/app/src/test/java/org/astraea/metrics/jmx/Utility.java b/app/src/test/java/org/astraea/app/metrics/jmx/Utility.java
similarity index 98%
rename from app/src/test/java/org/astraea/metrics/jmx/Utility.java
rename to app/src/test/java/org/astraea/app/metrics/jmx/Utility.java
index 69889404..514d867e 100644
--- a/app/src/test/java/org/astraea/metrics/jmx/Utility.java
+++ b/app/src/test/java/org/astraea/app/metrics/jmx/Utility.java
@@ -1,4 +1,4 @@
-package org.astraea.metrics.jmx;
+package org.astraea.app.metrics.jmx;
 
 import java.util.Map;
 import javax.management.Attribute;
diff --git a/app/src/test/java/org/astraea/metrics/kafka/KafkaMetricsTest.java b/app/src/test/java/org/astraea/app/metrics/kafka/KafkaMetricsTest.java
similarity index 96%
rename from app/src/test/java/org/astraea/metrics/kafka/KafkaMetricsTest.java
rename to app/src/test/java/org/astraea/app/metrics/kafka/KafkaMetricsTest.java
index 3306a3b2..d28d4f89 100644
--- a/app/src/test/java/org/astraea/metrics/kafka/KafkaMetricsTest.java
+++ b/app/src/test/java/org/astraea/app/metrics/kafka/KafkaMetricsTest.java
@@ -1,4 +1,4 @@
-package org.astraea.metrics.kafka;
+package org.astraea.app.metrics.kafka;
 
 import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
 import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -17,12 +17,12 @@ import javax.management.MBeanServer;
 import javax.management.remote.JMXConnectorServer;
 import javax.management.remote.JMXConnectorServerFactory;
 import javax.management.remote.JMXServiceURL;
-import org.astraea.admin.Admin;
-import org.astraea.common.Utils;
-import org.astraea.metrics.java.JvmMemory;
-import org.astraea.metrics.java.OperatingSystemInfo;
-import org.astraea.metrics.jmx.MBeanClient;
-import org.astraea.service.RequireBrokerCluster;
+import org.astraea.app.admin.Admin;
+import org.astraea.app.common.Utils;
+import org.astraea.app.metrics.java.JvmMemory;
+import org.astraea.app.metrics.java.OperatingSystemInfo;
+import org.astraea.app.metrics.jmx.MBeanClient;
+import org.astraea.app.service.RequireBrokerCluster;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
diff --git a/app/src/test/java/org/astraea/partitioner/ConfigurationTest.java b/app/src/test/java/org/astraea/app/partitioner/ConfigurationTest.java
similarity index 95%
rename from app/src/test/java/org/astraea/partitioner/ConfigurationTest.java
rename to app/src/test/java/org/astraea/app/partitioner/ConfigurationTest.java
index a186aef3..c07223ec 100644
--- a/app/src/test/java/org/astraea/partitioner/ConfigurationTest.java
+++ b/app/src/test/java/org/astraea/app/partitioner/ConfigurationTest.java
@@ -1,4 +1,4 @@
-package org.astraea.partitioner;
+package org.astraea.app.partitioner;
 
 import java.util.List;
 import java.util.Map;
diff --git a/app/src/test/java/org/astraea/partitioner/DispatcherTest.java b/app/src/test/java/org/astraea/app/partitioner/DispatcherTest.java
similarity index 93%
rename from app/src/test/java/org/astraea/partitioner/DispatcherTest.java
rename to app/src/test/java/org/astraea/app/partitioner/DispatcherTest.java
index d15917f4..ca241bd8 100644
--- a/app/src/test/java/org/astraea/partitioner/DispatcherTest.java
+++ b/app/src/test/java/org/astraea/app/partitioner/DispatcherTest.java
@@ -1,9 +1,9 @@
-package org.astraea.partitioner;
+package org.astraea.app.partitioner;
 
 import java.util.Map;
 import java.util.Objects;
 import java.util.concurrent.atomic.AtomicInteger;
-import org.astraea.cost.ClusterInfo;
+import org.astraea.app.cost.ClusterInfo;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
diff --git a/app/src/test/java/org/astraea/partitioner/PartitionerUtilsTest.java b/app/src/test/java/org/astraea/app/partitioner/PartitionerUtilsTest.java
similarity index 53%
rename from app/src/test/java/org/astraea/partitioner/PartitionerUtilsTest.java
rename to app/src/test/java/org/astraea/app/partitioner/PartitionerUtilsTest.java
index e99aad84..f5fee873 100644
--- a/app/src/test/java/org/astraea/partitioner/PartitionerUtilsTest.java
+++ b/app/src/test/java/org/astraea/app/partitioner/PartitionerUtilsTest.java
@@ -1,10 +1,5 @@
-package org.astraea.partitioner;
+package org.astraea.app.partitioner;
 
-import static org.astraea.partitioner.PartitionerUtils.allPoisson;
-import static org.astraea.partitioner.PartitionerUtils.doPoisson;
-import static org.astraea.partitioner.PartitionerUtils.factorial;
-import static org.astraea.partitioner.PartitionerUtils.parseIdJMXPort;
-import static org.astraea.partitioner.PartitionerUtils.weightPoisson;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
 import java.util.HashMap;
@@ -16,16 +11,16 @@ public class PartitionerUtilsTest {
 
   @Test
   void testFactorial() {
-    assertEquals(factorial(3), 6);
-    assertEquals(factorial(5), 120);
+    Assertions.assertEquals(PartitionerUtils.factorial(3), 6);
+    Assertions.assertEquals(PartitionerUtils.factorial(5), 120);
   }
 
   @Test
   void testDoPoisson() {
-    assertEquals(doPoisson(10, 15), 0.9512595966960214);
-    assertEquals(doPoisson(5, 5), 0.6159606548330632);
-    assertEquals(doPoisson(5, 8), 0.9319063652781515);
-    assertEquals(doPoisson(5, 2), 0.12465201948308113);
+    Assertions.assertEquals(PartitionerUtils.doPoisson(10, 15), 0.9512595966960214);
+    Assertions.assertEquals(PartitionerUtils.doPoisson(5, 5), 0.6159606548330632);
+    Assertions.assertEquals(PartitionerUtils.doPoisson(5, 8), 0.9319063652781515);
+    Assertions.assertEquals(PartitionerUtils.doPoisson(5, 2), 0.12465201948308113);
   }
 
   @Test
@@ -41,36 +36,37 @@ public class PartitionerUtilsTest {
     testPoissonMap.put(1, 0.6159606548330632);
     testPoissonMap.put(2, 0.9319063652781515);
 
-    poissonMap = allPoisson(testNodesLoadCount);
+    poissonMap = PartitionerUtils.allPoisson(testNodesLoadCount);
 
     assertEquals(poissonMap, testPoissonMap);
   }
 
   @Test
   void testWeightPoisson() {
-    Assertions.assertEquals(weightPoisson(0.5, 1.0), 10);
-    Assertions.assertEquals(weightPoisson(1.0, 1.0), 0);
-    Assertions.assertEquals(weightPoisson(0.95, 1.0), 0);
-    Assertions.assertEquals(weightPoisson(0.9, 1.0), 0);
-    Assertions.assertEquals(weightPoisson(0.0, 1.0), 20);
-    Assertions.assertEquals(weightPoisson(0.8, 1.0), 1);
+    Assertions.assertEquals(PartitionerUtils.weightPoisson(0.5, 1.0), 10);
+    Assertions.assertEquals(PartitionerUtils.weightPoisson(1.0, 1.0), 0);
+    Assertions.assertEquals(PartitionerUtils.weightPoisson(0.95, 1.0), 0);
+    Assertions.assertEquals(PartitionerUtils.weightPoisson(0.9, 1.0), 0);
+    Assertions.assertEquals(PartitionerUtils.weightPoisson(0.0, 1.0), 20);
+    Assertions.assertEquals(PartitionerUtils.weightPoisson(0.8, 1.0), 1);
   }
 
   @Test
   void testParseIdJMXPort() {
     var config =
         Configuration.of(Map.of("broker.1001.jmx.port", "8000", "broker.1002.jmx.port", "8001"));
-    var ans = parseIdJMXPort(config);
+    var ans = PartitionerUtils.parseIdJMXPort(config);
     Assertions.assertEquals(2, ans.size());
     Assertions.assertEquals(8000, ans.get(1001));
     Assertions.assertEquals(8001, ans.get(1002));
 
     config = Configuration.of(Map.of("jmx.port", "8000", "broker.1002.jmx.port", "8001"));
-    ans = parseIdJMXPort(config);
+    ans = PartitionerUtils.parseIdJMXPort(config);
     Assertions.assertEquals(1, ans.size());
     Assertions.assertEquals(8001, ans.get(1002));
 
     var config3 = Configuration.of(Map.of("broker.id.jmx.port", "8000"));
-    Assertions.assertThrows(NumberFormatException.class, () -> parseIdJMXPort(config3));
+    Assertions.assertThrows(
+        NumberFormatException.class, () -> PartitionerUtils.parseIdJMXPort(config3));
   }
 }
diff --git a/app/src/test/java/org/astraea/partitioner/StrictCostDispatcherTest.java b/app/src/test/java/org/astraea/app/partitioner/StrictCostDispatcherTest.java
similarity index 86%
rename from app/src/test/java/org/astraea/partitioner/StrictCostDispatcherTest.java
rename to app/src/test/java/org/astraea/app/partitioner/StrictCostDispatcherTest.java
index ca541842..b52a8b1d 100644
--- a/app/src/test/java/org/astraea/partitioner/StrictCostDispatcherTest.java
+++ b/app/src/test/java/org/astraea/app/partitioner/StrictCostDispatcherTest.java
@@ -1,4 +1,4 @@
-package org.astraea.partitioner;
+package org.astraea.app.partitioner;
 
 import java.util.List;
 import java.util.Map;
@@ -6,15 +6,15 @@ import java.util.NoSuchElementException;
 import java.util.Set;
 import java.util.function.Function;
 import java.util.stream.Collectors;
-import org.astraea.cost.BrokerCost;
-import org.astraea.cost.ClusterInfo;
-import org.astraea.cost.HasBrokerCost;
-import org.astraea.cost.NodeInfo;
-import org.astraea.cost.ReplicaInfo;
-import org.astraea.cost.ThroughputCost;
-import org.astraea.cost.broker.BrokerInputCost;
-import org.astraea.metrics.collector.Fetcher;
-import org.astraea.metrics.collector.Receiver;
+import org.astraea.app.cost.BrokerCost;
+import org.astraea.app.cost.ClusterInfo;
+import org.astraea.app.cost.HasBrokerCost;
+import org.astraea.app.cost.NodeInfo;
+import org.astraea.app.cost.ReplicaInfo;
+import org.astraea.app.cost.ThroughputCost;
+import org.astraea.app.cost.broker.BrokerInputCost;
+import org.astraea.app.metrics.collector.Fetcher;
+import org.astraea.app.metrics.collector.Receiver;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 import org.mockito.Mockito;
@@ -160,20 +160,24 @@ public class StrictCostDispatcherTest {
     var config =
         Configuration.of(
             Map.of(
-                "org.astraea.cost.broker.BrokerInputCost",
+                "org.astraea.app.cost.broker.BrokerInputCost",
                 "20",
-                "org.astraea.cost.broker.BrokerOutputCost",
+                "org.astraea.app.cost.broker.BrokerOutputCost",
                 "1.25"));
     var ans = StrictCostDispatcher.parseCostFunctionWeight(config);
     Assertions.assertEquals(2, ans.size());
     for (var entry : ans.entrySet()) {
-      if (entry.getKey().getClass().getName().equals("org.astraea.cost.broker.BrokerInputCost")) {
+      if (entry
+          .getKey()
+          .getClass()
+          .getName()
+          .equals("org.astraea.app.cost.broker.BrokerInputCost")) {
         Assertions.assertEquals(20.0, entry.getValue());
       } else if (entry
           .getKey()
           .getClass()
           .getName()
-          .equals("org.astraea.cost.broker.BrokerOutputCost")) {
+          .equals("org.astraea.app.cost.broker.BrokerOutputCost")) {
         Assertions.assertEquals(1.25, entry.getValue());
       } else {
         Assertions.assertEquals(0.0, entry.getValue());
@@ -184,9 +188,9 @@ public class StrictCostDispatcherTest {
     var config2 =
         Configuration.of(
             Map.of(
-                "org.astraea.cost.broker.BrokerInputCost",
+                "org.astraea.app.cost.broker.BrokerInputCost",
                 "-20",
-                "org.astraea.cost.broker.BrokerOutputCost",
+                "org.astraea.app.cost.broker.BrokerOutputCost",
                 "1.25"));
     Assertions.assertThrows(
         IllegalArgumentException.class,
diff --git a/app/src/test/java/org/astraea/partitioner/smooth/SmoothWeightRoundRobinDispatchTest.java b/app/src/test/java/org/astraea/app/partitioner/smooth/SmoothWeightRoundRobinDispatchTest.java
similarity index 94%
rename from app/src/test/java/org/astraea/partitioner/smooth/SmoothWeightRoundRobinDispatchTest.java
rename to app/src/test/java/org/astraea/app/partitioner/smooth/SmoothWeightRoundRobinDispatchTest.java
index 06ee2aa6..de765ab3 100644
--- a/app/src/test/java/org/astraea/partitioner/smooth/SmoothWeightRoundRobinDispatchTest.java
+++ b/app/src/test/java/org/astraea/app/partitioner/smooth/SmoothWeightRoundRobinDispatchTest.java
@@ -1,4 +1,4 @@
-package org.astraea.partitioner.smooth;
+package org.astraea.app.partitioner.smooth;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
@@ -16,19 +16,19 @@ import java.util.stream.Collectors;
 import java.util.stream.IntStream;
 import org.apache.kafka.clients.producer.ProducerConfig;
 import org.apache.kafka.common.serialization.ByteArraySerializer;
-import org.astraea.admin.Admin;
-import org.astraea.concurrent.Executor;
-import org.astraea.concurrent.State;
-import org.astraea.concurrent.ThreadPool;
-import org.astraea.consumer.Consumer;
-import org.astraea.consumer.Deserializer;
-import org.astraea.consumer.Header;
-import org.astraea.cost.FakeClusterInfo;
-import org.astraea.cost.NodeInfo;
-import org.astraea.cost.ReplicaInfo;
-import org.astraea.producer.Producer;
-import org.astraea.producer.Serializer;
-import org.astraea.service.RequireBrokerCluster;
+import org.astraea.app.admin.Admin;
+import org.astraea.app.concurrent.Executor;
+import org.astraea.app.concurrent.State;
+import org.astraea.app.concurrent.ThreadPool;
+import org.astraea.app.consumer.Consumer;
+import org.astraea.app.consumer.Deserializer;
+import org.astraea.app.consumer.Header;
+import org.astraea.app.cost.FakeClusterInfo;
+import org.astraea.app.cost.NodeInfo;
+import org.astraea.app.cost.ReplicaInfo;
+import org.astraea.app.producer.Producer;
+import org.astraea.app.producer.Serializer;
+import org.astraea.app.service.RequireBrokerCluster;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 import org.mockito.Mockito;
diff --git a/app/src/test/java/org/astraea/partitioner/smooth/SmoothWeightRoundRobinTest.java b/app/src/test/java/org/astraea/app/partitioner/smooth/SmoothWeightRoundRobinTest.java
similarity index 92%
rename from app/src/test/java/org/astraea/partitioner/smooth/SmoothWeightRoundRobinTest.java
rename to app/src/test/java/org/astraea/app/partitioner/smooth/SmoothWeightRoundRobinTest.java
index 1fd6de80..e3517a81 100644
--- a/app/src/test/java/org/astraea/partitioner/smooth/SmoothWeightRoundRobinTest.java
+++ b/app/src/test/java/org/astraea/app/partitioner/smooth/SmoothWeightRoundRobinTest.java
@@ -1,11 +1,11 @@
-package org.astraea.partitioner.smooth;
+package org.astraea.app.partitioner.smooth;
 
 import java.util.List;
 import java.util.Map;
-import org.astraea.cost.ClusterInfo;
-import org.astraea.cost.FakeClusterInfo;
-import org.astraea.cost.NodeInfo;
-import org.astraea.cost.ReplicaInfo;
+import org.astraea.app.cost.ClusterInfo;
+import org.astraea.app.cost.FakeClusterInfo;
+import org.astraea.app.cost.NodeInfo;
+import org.astraea.app.cost.ReplicaInfo;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 import org.mockito.Mockito;
diff --git a/app/src/test/java/org/astraea/performance/DataSupplierTest.java b/app/src/test/java/org/astraea/app/performance/DataSupplierTest.java
similarity index 97%
rename from app/src/test/java/org/astraea/performance/DataSupplierTest.java
rename to app/src/test/java/org/astraea/app/performance/DataSupplierTest.java
index ee0707b7..52aa988b 100644
--- a/app/src/test/java/org/astraea/performance/DataSupplierTest.java
+++ b/app/src/test/java/org/astraea/app/performance/DataSupplierTest.java
@@ -1,7 +1,7 @@
-package org.astraea.performance;
+package org.astraea.app.performance;
 
 import java.util.concurrent.TimeUnit;
-import org.astraea.common.DataUnit;
+import org.astraea.app.common.DataUnit;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
diff --git a/app/src/test/java/org/astraea/performance/DistributionTest.java b/app/src/test/java/org/astraea/app/performance/DistributionTest.java
similarity index 97%
rename from app/src/test/java/org/astraea/performance/DistributionTest.java
rename to app/src/test/java/org/astraea/app/performance/DistributionTest.java
index a227e19a..f55a2a82 100644
--- a/app/src/test/java/org/astraea/performance/DistributionTest.java
+++ b/app/src/test/java/org/astraea/app/performance/DistributionTest.java
@@ -1,4 +1,4 @@
-package org.astraea.performance;
+package org.astraea.app.performance;
 
 import java.util.Random;
 import java.util.stream.Collectors;
diff --git a/app/src/test/java/org/astraea/performance/ExeTimeTest.java b/app/src/test/java/org/astraea/app/performance/ExeTimeTest.java
similarity index 97%
rename from app/src/test/java/org/astraea/performance/ExeTimeTest.java
rename to app/src/test/java/org/astraea/app/performance/ExeTimeTest.java
index 1cf7bb0c..64016b9a 100644
--- a/app/src/test/java/org/astraea/performance/ExeTimeTest.java
+++ b/app/src/test/java/org/astraea/app/performance/ExeTimeTest.java
@@ -1,4 +1,4 @@
-package org.astraea.performance;
+package org.astraea.app.performance;
 
 import com.beust.jcommander.ParameterException;
 import org.junit.jupiter.api.Assertions;
diff --git a/app/src/test/java/org/astraea/performance/ManagerTest.java b/app/src/test/java/org/astraea/app/performance/ManagerTest.java
similarity index 97%
rename from app/src/test/java/org/astraea/performance/ManagerTest.java
rename to app/src/test/java/org/astraea/app/performance/ManagerTest.java
index 8ebca7f4..52efc89c 100644
--- a/app/src/test/java/org/astraea/performance/ManagerTest.java
+++ b/app/src/test/java/org/astraea/app/performance/ManagerTest.java
@@ -1,4 +1,4 @@
-package org.astraea.performance;
+package org.astraea.app.performance;
 
 import java.util.List;
 import org.junit.jupiter.api.Assertions;
diff --git a/app/src/test/java/org/astraea/performance/MetricsTest.java b/app/src/test/java/org/astraea/app/performance/MetricsTest.java
similarity index 96%
rename from app/src/test/java/org/astraea/performance/MetricsTest.java
rename to app/src/test/java/org/astraea/app/performance/MetricsTest.java
index e2c23a78..b25a93da 100644
--- a/app/src/test/java/org/astraea/performance/MetricsTest.java
+++ b/app/src/test/java/org/astraea/app/performance/MetricsTest.java
@@ -1,4 +1,4 @@
-package org.astraea.performance;
+package org.astraea.app.performance;
 
 import java.util.Random;
 import org.junit.jupiter.api.Assertions;
diff --git a/app/src/test/java/org/astraea/performance/PerformanceTest.java b/app/src/test/java/org/astraea/app/performance/PerformanceTest.java
similarity index 75%
rename from app/src/test/java/org/astraea/performance/PerformanceTest.java
rename to app/src/test/java/org/astraea/app/performance/PerformanceTest.java
index ac93dcac..3f428961 100644
--- a/app/src/test/java/org/astraea/performance/PerformanceTest.java
+++ b/app/src/test/java/org/astraea/app/performance/PerformanceTest.java
@@ -1,4 +1,4 @@
-package org.astraea.performance;
+package org.astraea.app.performance;
 
 import com.beust.jcommander.ParameterException;
 import java.nio.charset.StandardCharsets;
@@ -8,14 +8,15 @@ import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
 import java.util.function.BiConsumer;
-import org.astraea.admin.Admin;
-import org.astraea.admin.TopicPartition;
-import org.astraea.concurrent.Executor;
-import org.astraea.concurrent.State;
-import org.astraea.consumer.Consumer;
-import org.astraea.consumer.Isolation;
-import org.astraea.producer.Producer;
-import org.astraea.service.RequireBrokerCluster;
+import org.astraea.app.admin.Admin;
+import org.astraea.app.admin.TopicPartition;
+import org.astraea.app.argument.Argument;
+import org.astraea.app.concurrent.Executor;
+import org.astraea.app.concurrent.State;
+import org.astraea.app.consumer.Consumer;
+import org.astraea.app.consumer.Isolation;
+import org.astraea.app.producer.Producer;
+import org.astraea.app.service.RequireBrokerCluster;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
@@ -29,7 +30,7 @@ public class PerformanceTest extends RequireBrokerCluster {
     };
     var latch = new CountDownLatch(1);
     BiConsumer<Long, Long> observer = (x, y) -> latch.countDown();
-    var argument = org.astraea.argument.Argument.parse(new Performance.Argument(), arguments1);
+    var argument = Argument.parse(new Performance.Argument(), arguments1);
     var producerExecutors =
         Performance.producerExecutors(
             argument,
@@ -51,7 +52,7 @@ public class PerformanceTest extends RequireBrokerCluster {
     };
     var latch = new CountDownLatch(1);
     BiConsumer<Long, Long> observer = (x, y) -> latch.countDown();
-    var argument = org.astraea.argument.Argument.parse(new Performance.Argument(), arguments1);
+    var argument = Argument.parse(new Performance.Argument(), arguments1);
     var producerExecutors =
         Performance.producerExecutors(
             argument,
@@ -148,61 +149,51 @@ public class PerformanceTest extends RequireBrokerCluster {
       "key=value"
     };
 
-    var arg = org.astraea.argument.Argument.parse(new Performance.Argument(), arguments1);
+    var arg = Argument.parse(new Performance.Argument(), arguments1);
     Assertions.assertEquals("value", arg.configs().get("key"));
 
     String[] arguments2 = {"--bootstrap.servers", "localhost:9092", "--topic", ""};
     Assertions.assertThrows(
-        ParameterException.class,
-        () -> org.astraea.argument.Argument.parse(new Performance.Argument(), arguments2));
+        ParameterException.class, () -> Argument.parse(new Performance.Argument(), arguments2));
 
     String[] arguments3 = {"--bootstrap.servers", "localhost:9092", "--replicas", "0"};
     Assertions.assertThrows(
-        ParameterException.class,
-        () -> org.astraea.argument.Argument.parse(new Performance.Argument(), arguments3));
+        ParameterException.class, () -> Argument.parse(new Performance.Argument(), arguments3));
 
     String[] arguments4 = {"--bootstrap.servers", "localhost:9092", "--partitions", "0"};
     Assertions.assertThrows(
-        ParameterException.class,
-        () -> org.astraea.argument.Argument.parse(new Performance.Argument(), arguments4));
+        ParameterException.class, () -> Argument.parse(new Performance.Argument(), arguments4));
 
     String[] arguments5 = {"--bootstrap.servers", "localhost:9092", "--producers", "0"};
     Assertions.assertThrows(
-        ParameterException.class,
-        () -> org.astraea.argument.Argument.parse(new Performance.Argument(), arguments5));
+        ParameterException.class, () -> Argument.parse(new Performance.Argument(), arguments5));
 
     String[] arguments6 = {"--bootstrap.servers", "localhost:9092", "--consumers", "0"};
-    Assertions.assertDoesNotThrow(
-        () -> org.astraea.argument.Argument.parse(new Performance.Argument(), arguments6));
+    Assertions.assertDoesNotThrow(() -> Argument.parse(new Performance.Argument(), arguments6));
 
     String[] arguments7 = {"--bootstrap.servers", "localhost:9092", "--run.until", "1"};
     Assertions.assertThrows(
-        ParameterException.class,
-        () -> org.astraea.argument.Argument.parse(new Performance.Argument(), arguments7));
+        ParameterException.class, () -> Argument.parse(new Performance.Argument(), arguments7));
 
     String[] arguments8 = {"--bootstrap.servers", "localhost:9092", "--record.size", "1"};
     Assertions.assertThrows(
         IllegalArgumentException.class,
-        () -> org.astraea.argument.Argument.parse(new Performance.Argument(), arguments8));
+        () -> Argument.parse(new Performance.Argument(), arguments8));
 
     String[] arguments10 = {"--bootstrap.servers", "localhost:9092", "--partitioner", ""};
     Assertions.assertThrows(
-        ParameterException.class,
-        () -> org.astraea.argument.Argument.parse(new Performance.Argument(), arguments10));
+        ParameterException.class, () -> Argument.parse(new Performance.Argument(), arguments10));
 
     String[] arguments11 = {"--bootstrap.servers", "localhost:9092", "--compression", ""};
     Assertions.assertThrows(
-        ParameterException.class,
-        () -> org.astraea.argument.Argument.parse(new Performance.Argument(), arguments11));
+        ParameterException.class, () -> Argument.parse(new Performance.Argument(), arguments11));
 
     String[] arguments12 = {"--bootstrap.servers", "localhost:9092", "--key.distribution", ""};
     Assertions.assertThrows(
-        ParameterException.class,
-        () -> org.astraea.argument.Argument.parse(new Performance.Argument(), arguments12));
+        ParameterException.class, () -> Argument.parse(new Performance.Argument(), arguments12));
 
     String[] arguments13 = {"--bootstrap.servers", "localhost:9092", "--specify.broker", ""};
     Assertions.assertThrows(
-        ParameterException.class,
-        () -> org.astraea.argument.Argument.parse(new Performance.Argument(), arguments13));
+        ParameterException.class, () -> Argument.parse(new Performance.Argument(), arguments13));
   }
 }
diff --git a/app/src/test/java/org/astraea/performance/ProducerExecutorTest.java b/app/src/test/java/org/astraea/app/performance/ProducerExecutorTest.java
similarity index 94%
rename from app/src/test/java/org/astraea/performance/ProducerExecutorTest.java
rename to app/src/test/java/org/astraea/app/performance/ProducerExecutorTest.java
index 02a1bf0f..904902be 100644
--- a/app/src/test/java/org/astraea/performance/ProducerExecutorTest.java
+++ b/app/src/test/java/org/astraea/app/performance/ProducerExecutorTest.java
@@ -1,4 +1,4 @@
-package org.astraea.performance;
+package org.astraea.app.performance;
 
 import java.nio.charset.StandardCharsets;
 import java.util.Set;
@@ -8,12 +8,12 @@ import java.util.concurrent.TimeUnit;
 import java.util.function.BiConsumer;
 import java.util.function.Supplier;
 import java.util.stream.Stream;
-import org.astraea.admin.Admin;
-import org.astraea.admin.TopicPartition;
-import org.astraea.common.Utils;
-import org.astraea.concurrent.State;
-import org.astraea.producer.Producer;
-import org.astraea.service.RequireBrokerCluster;
+import org.astraea.app.admin.Admin;
+import org.astraea.app.admin.TopicPartition;
+import org.astraea.app.common.Utils;
+import org.astraea.app.concurrent.State;
+import org.astraea.app.producer.Producer;
+import org.astraea.app.service.RequireBrokerCluster;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Named;
 import org.junit.jupiter.params.ParameterizedTest;
diff --git a/app/src/test/java/org/astraea/performance/TrackerTest.java b/app/src/test/java/org/astraea/app/performance/TrackerTest.java
similarity index 96%
rename from app/src/test/java/org/astraea/performance/TrackerTest.java
rename to app/src/test/java/org/astraea/app/performance/TrackerTest.java
index 2ae05a67..df3fdb4d 100644
--- a/app/src/test/java/org/astraea/performance/TrackerTest.java
+++ b/app/src/test/java/org/astraea/app/performance/TrackerTest.java
@@ -1,8 +1,8 @@
-package org.astraea.performance;
+package org.astraea.app.performance;
 
 import java.util.List;
 import java.util.concurrent.atomic.AtomicBoolean;
-import org.astraea.concurrent.State;
+import org.astraea.app.concurrent.State;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
diff --git a/app/src/test/java/org/astraea/producer/ProducerTest.java b/app/src/test/java/org/astraea/app/producer/ProducerTest.java
similarity index 95%
rename from app/src/test/java/org/astraea/producer/ProducerTest.java
rename to app/src/test/java/org/astraea/app/producer/ProducerTest.java
index 813136d6..0f7f8adc 100644
--- a/app/src/test/java/org/astraea/producer/ProducerTest.java
+++ b/app/src/test/java/org/astraea/app/producer/ProducerTest.java
@@ -1,4 +1,4 @@
-package org.astraea.producer;
+package org.astraea.app.producer;
 
 import java.time.Duration;
 import java.util.ArrayList;
@@ -9,12 +9,12 @@ import java.util.concurrent.ExecutionException;
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
 import java.util.stream.Stream;
-import org.astraea.common.Utils;
-import org.astraea.consumer.Consumer;
-import org.astraea.consumer.Deserializer;
-import org.astraea.consumer.Header;
-import org.astraea.consumer.Isolation;
-import org.astraea.service.RequireBrokerCluster;
+import org.astraea.app.common.Utils;
+import org.astraea.app.consumer.Consumer;
+import org.astraea.app.consumer.Deserializer;
+import org.astraea.app.consumer.Header;
+import org.astraea.app.consumer.Isolation;
+import org.astraea.app.service.RequireBrokerCluster;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Named;
 import org.junit.jupiter.api.Test;
diff --git a/app/src/test/java/org/astraea/service/BrokerCluster.java b/app/src/test/java/org/astraea/app/service/BrokerCluster.java
similarity index 90%
rename from app/src/test/java/org/astraea/service/BrokerCluster.java
rename to app/src/test/java/org/astraea/app/service/BrokerCluster.java
index 338f69ca..a7d0d4e2 100644
--- a/app/src/test/java/org/astraea/service/BrokerCluster.java
+++ b/app/src/test/java/org/astraea/app/service/BrokerCluster.java
@@ -1,4 +1,4 @@
-package org.astraea.service;
+package org.astraea.app.service;
 
 import java.util.Map;
 import java.util.Set;
diff --git a/app/src/test/java/org/astraea/service/Database.java b/app/src/test/java/org/astraea/app/service/Database.java
similarity index 98%
rename from app/src/test/java/org/astraea/service/Database.java
rename to app/src/test/java/org/astraea/app/service/Database.java
index b1078bf1..0993ab7d 100644
--- a/app/src/test/java/org/astraea/service/Database.java
+++ b/app/src/test/java/org/astraea/app/service/Database.java
@@ -1,4 +1,4 @@
-package org.astraea.service;
+package org.astraea.app.service;
 
 import static com.wix.mysql.EmbeddedMysql.anEmbeddedMysql;
 import static com.wix.mysql.config.Charset.UTF8;
@@ -10,7 +10,7 @@ import java.sql.Connection;
 import java.sql.DriverManager;
 import java.util.Calendar;
 import java.util.concurrent.TimeUnit;
-import org.astraea.common.Utils;
+import org.astraea.app.common.Utils;
 
 public interface Database extends Closeable {
   static Database mysql() {
diff --git a/app/src/test/java/org/astraea/service/DatabaseTest.java b/app/src/test/java/org/astraea/app/service/DatabaseTest.java
similarity index 92%
rename from app/src/test/java/org/astraea/service/DatabaseTest.java
rename to app/src/test/java/org/astraea/app/service/DatabaseTest.java
index 6c9c3f6c..3d35c5e9 100644
--- a/app/src/test/java/org/astraea/service/DatabaseTest.java
+++ b/app/src/test/java/org/astraea/app/service/DatabaseTest.java
@@ -1,6 +1,6 @@
-package org.astraea.service;
+package org.astraea.app.service;
 
-import org.astraea.common.Utils;
+import org.astraea.app.common.Utils;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
diff --git a/app/src/test/java/org/astraea/service/RequireBrokerCluster.java b/app/src/test/java/org/astraea/app/service/RequireBrokerCluster.java
similarity index 92%
rename from app/src/test/java/org/astraea/service/RequireBrokerCluster.java
rename to app/src/test/java/org/astraea/app/service/RequireBrokerCluster.java
index 82b3c83c..49d2b19b 100644
--- a/app/src/test/java/org/astraea/service/RequireBrokerCluster.java
+++ b/app/src/test/java/org/astraea/app/service/RequireBrokerCluster.java
@@ -1,8 +1,8 @@
-package org.astraea.service;
+package org.astraea.app.service;
 
 import java.util.Map;
 import java.util.Set;
-import org.astraea.common.Utils;
+import org.astraea.app.common.Utils;
 import org.junit.jupiter.api.AfterAll;
 
 /**
diff --git a/app/src/test/java/org/astraea/service/RequireJmxServer.java b/app/src/test/java/org/astraea/app/service/RequireJmxServer.java
similarity index 97%
rename from app/src/test/java/org/astraea/service/RequireJmxServer.java
rename to app/src/test/java/org/astraea/app/service/RequireJmxServer.java
index 5bd35248..8ac866f6 100644
--- a/app/src/test/java/org/astraea/service/RequireJmxServer.java
+++ b/app/src/test/java/org/astraea/app/service/RequireJmxServer.java
@@ -1,4 +1,4 @@
-package org.astraea.service;
+package org.astraea.app.service;
 
 import java.io.IOException;
 import java.io.UncheckedIOException;
@@ -10,7 +10,7 @@ import java.rmi.registry.LocateRegistry;
 import javax.management.remote.JMXConnectorServer;
 import javax.management.remote.JMXConnectorServerFactory;
 import javax.management.remote.JMXServiceURL;
-import org.astraea.common.Utils;
+import org.astraea.app.common.Utils;
 import org.junit.jupiter.api.AfterAll;
 
 public abstract class RequireJmxServer {
diff --git a/app/src/test/java/org/astraea/service/RequireJmxServerTest.java b/app/src/test/java/org/astraea/app/service/RequireJmxServerTest.java
similarity index 88%
rename from app/src/test/java/org/astraea/service/RequireJmxServerTest.java
rename to app/src/test/java/org/astraea/app/service/RequireJmxServerTest.java
index f2778317..80fcdc53 100644
--- a/app/src/test/java/org/astraea/service/RequireJmxServerTest.java
+++ b/app/src/test/java/org/astraea/app/service/RequireJmxServerTest.java
@@ -1,9 +1,9 @@
-package org.astraea.service;
+package org.astraea.app.service;
 
 import java.util.Set;
-import org.astraea.metrics.jmx.BeanQuery;
-import org.astraea.metrics.jmx.MBeanClient;
-import org.astraea.metrics.kafka.KafkaMetrics;
+import org.astraea.app.metrics.jmx.BeanQuery;
+import org.astraea.app.metrics.jmx.MBeanClient;
+import org.astraea.app.metrics.kafka.KafkaMetrics;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
diff --git a/app/src/test/java/org/astraea/service/Services.java b/app/src/test/java/org/astraea/app/service/Services.java
similarity index 98%
rename from app/src/test/java/org/astraea/service/Services.java
rename to app/src/test/java/org/astraea/app/service/Services.java
index 5097583a..587b65df 100644
--- a/app/src/test/java/org/astraea/service/Services.java
+++ b/app/src/test/java/org/astraea/app/service/Services.java
@@ -1,4 +1,4 @@
-package org.astraea.service;
+package org.astraea.app.service;
 
 import java.io.File;
 import java.net.InetSocketAddress;
@@ -15,7 +15,7 @@ import org.apache.kafka.common.network.ListenerName;
 import org.apache.kafka.common.utils.SystemTime;
 import org.apache.zookeeper.server.NIOServerCnxnFactory;
 import org.apache.zookeeper.server.ZooKeeperServer;
-import org.astraea.common.Utils;
+import org.astraea.app.common.Utils;
 
 public final class Services {
 
diff --git a/app/src/test/java/org/astraea/service/ZookeeperCluster.java b/app/src/test/java/org/astraea/app/service/ZookeeperCluster.java
similarity index 83%
rename from app/src/test/java/org/astraea/service/ZookeeperCluster.java
rename to app/src/test/java/org/astraea/app/service/ZookeeperCluster.java
index 28f41d82..0f704834 100644
--- a/app/src/test/java/org/astraea/service/ZookeeperCluster.java
+++ b/app/src/test/java/org/astraea/app/service/ZookeeperCluster.java
@@ -1,4 +1,4 @@
-package org.astraea.service;
+package org.astraea.app.service;
 
 public interface ZookeeperCluster extends AutoCloseable {
 
diff --git a/app/src/test/java/org/astraea/web/BrokerHandlerTest.java b/app/src/test/java/org/astraea/app/web/BrokerHandlerTest.java
similarity index 95%
rename from app/src/test/java/org/astraea/web/BrokerHandlerTest.java
rename to app/src/test/java/org/astraea/app/web/BrokerHandlerTest.java
index 2d4a0035..cd88dfd4 100644
--- a/app/src/test/java/org/astraea/web/BrokerHandlerTest.java
+++ b/app/src/test/java/org/astraea/app/web/BrokerHandlerTest.java
@@ -1,13 +1,13 @@
-package org.astraea.web;
+package org.astraea.app.web;
 
 import java.util.Map;
 import java.util.NoSuchElementException;
 import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
-import org.astraea.admin.Admin;
-import org.astraea.common.Utils;
-import org.astraea.service.RequireBrokerCluster;
+import org.astraea.app.admin.Admin;
+import org.astraea.app.common.Utils;
+import org.astraea.app.service.RequireBrokerCluster;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
diff --git a/app/src/test/java/org/astraea/web/ErrorObjectTest.java b/app/src/test/java/org/astraea/app/web/ErrorObjectTest.java
similarity index 90%
rename from app/src/test/java/org/astraea/web/ErrorObjectTest.java
rename to app/src/test/java/org/astraea/app/web/ErrorObjectTest.java
index 44404c1e..5a8dd807 100644
--- a/app/src/test/java/org/astraea/web/ErrorObjectTest.java
+++ b/app/src/test/java/org/astraea/app/web/ErrorObjectTest.java
@@ -1,4 +1,4 @@
-package org.astraea.web;
+package org.astraea.app.web;
 
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
diff --git a/app/src/test/java/org/astraea/web/GroupHandlerTest.java b/app/src/test/java/org/astraea/app/web/GroupHandlerTest.java
similarity index 94%
rename from app/src/test/java/org/astraea/web/GroupHandlerTest.java
rename to app/src/test/java/org/astraea/app/web/GroupHandlerTest.java
index af667ef8..d3c045c9 100644
--- a/app/src/test/java/org/astraea/web/GroupHandlerTest.java
+++ b/app/src/test/java/org/astraea/app/web/GroupHandlerTest.java
@@ -1,4 +1,4 @@
-package org.astraea.web;
+package org.astraea.app.web;
 
 import java.time.Duration;
 import java.util.Map;
@@ -6,10 +6,10 @@ import java.util.NoSuchElementException;
 import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
-import org.astraea.admin.Admin;
-import org.astraea.common.Utils;
-import org.astraea.consumer.Consumer;
-import org.astraea.service.RequireBrokerCluster;
+import org.astraea.app.admin.Admin;
+import org.astraea.app.common.Utils;
+import org.astraea.app.consumer.Consumer;
+import org.astraea.app.service.RequireBrokerCluster;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
diff --git a/app/src/test/java/org/astraea/web/HandlerTest.java b/app/src/test/java/org/astraea/app/web/HandlerTest.java
similarity index 98%
rename from app/src/test/java/org/astraea/web/HandlerTest.java
rename to app/src/test/java/org/astraea/app/web/HandlerTest.java
index f5e1c9f4..12cc5c5a 100644
--- a/app/src/test/java/org/astraea/web/HandlerTest.java
+++ b/app/src/test/java/org/astraea/app/web/HandlerTest.java
@@ -1,4 +1,4 @@
-package org.astraea.web;
+package org.astraea.app.web;
 
 import com.sun.net.httpserver.HttpExchange;
 import java.net.URI;
diff --git a/app/src/test/java/org/astraea/web/PipelineHandlerTest.java b/app/src/test/java/org/astraea/app/web/PipelineHandlerTest.java
similarity index 91%
rename from app/src/test/java/org/astraea/web/PipelineHandlerTest.java
rename to app/src/test/java/org/astraea/app/web/PipelineHandlerTest.java
index 7caa9223..072961e3 100644
--- a/app/src/test/java/org/astraea/web/PipelineHandlerTest.java
+++ b/app/src/test/java/org/astraea/app/web/PipelineHandlerTest.java
@@ -1,13 +1,13 @@
-package org.astraea.web;
+package org.astraea.app.web;
 
 import java.util.Map;
 import java.util.Optional;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
-import org.astraea.admin.Admin;
-import org.astraea.common.Utils;
-import org.astraea.producer.Producer;
-import org.astraea.service.RequireBrokerCluster;
+import org.astraea.app.admin.Admin;
+import org.astraea.app.common.Utils;
+import org.astraea.app.producer.Producer;
+import org.astraea.app.service.RequireBrokerCluster;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 import org.mockito.Mockito;
diff --git a/app/src/test/java/org/astraea/web/PostRequestTest.java b/app/src/test/java/org/astraea/app/web/PostRequestTest.java
similarity index 97%
rename from app/src/test/java/org/astraea/web/PostRequestTest.java
rename to app/src/test/java/org/astraea/app/web/PostRequestTest.java
index 6fe5dfaa..c45a860f 100644
--- a/app/src/test/java/org/astraea/web/PostRequestTest.java
+++ b/app/src/test/java/org/astraea/app/web/PostRequestTest.java
@@ -1,4 +1,4 @@
-package org.astraea.web;
+package org.astraea.app.web;
 
 import com.sun.net.httpserver.HttpExchange;
 import java.io.ByteArrayInputStream;
diff --git a/app/src/test/java/org/astraea/web/ProducerHandlerTest.java b/app/src/test/java/org/astraea/app/web/ProducerHandlerTest.java
similarity index 95%
rename from app/src/test/java/org/astraea/web/ProducerHandlerTest.java
rename to app/src/test/java/org/astraea/app/web/ProducerHandlerTest.java
index 11f96509..8784d7a9 100644
--- a/app/src/test/java/org/astraea/web/ProducerHandlerTest.java
+++ b/app/src/test/java/org/astraea/app/web/ProducerHandlerTest.java
@@ -1,4 +1,4 @@
-package org.astraea.web;
+package org.astraea.app.web;
 
 import java.util.Map;
 import java.util.Optional;
@@ -6,10 +6,10 @@ import java.util.Set;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
-import org.astraea.admin.Admin;
-import org.astraea.common.Utils;
-import org.astraea.producer.Producer;
-import org.astraea.service.RequireBrokerCluster;
+import org.astraea.app.admin.Admin;
+import org.astraea.app.common.Utils;
+import org.astraea.app.producer.Producer;
+import org.astraea.app.service.RequireBrokerCluster;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
diff --git a/app/src/test/java/org/astraea/web/QuotaHandlerTest.java b/app/src/test/java/org/astraea/app/web/QuotaHandlerTest.java
similarity index 94%
rename from app/src/test/java/org/astraea/web/QuotaHandlerTest.java
rename to app/src/test/java/org/astraea/app/web/QuotaHandlerTest.java
index 3c15b375..31954265 100644
--- a/app/src/test/java/org/astraea/web/QuotaHandlerTest.java
+++ b/app/src/test/java/org/astraea/app/web/QuotaHandlerTest.java
@@ -1,10 +1,10 @@
-package org.astraea.web;
+package org.astraea.app.web;
 
 import java.util.Map;
 import java.util.Optional;
-import org.astraea.admin.Admin;
-import org.astraea.admin.Quota;
-import org.astraea.service.RequireBrokerCluster;
+import org.astraea.app.admin.Admin;
+import org.astraea.app.admin.Quota;
+import org.astraea.app.service.RequireBrokerCluster;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
diff --git a/app/src/test/java/org/astraea/web/TopicHandlerTest.java b/app/src/test/java/org/astraea/app/web/TopicHandlerTest.java
similarity index 97%
rename from app/src/test/java/org/astraea/web/TopicHandlerTest.java
rename to app/src/test/java/org/astraea/app/web/TopicHandlerTest.java
index 96cb70dc..07a1f58f 100644
--- a/app/src/test/java/org/astraea/web/TopicHandlerTest.java
+++ b/app/src/test/java/org/astraea/app/web/TopicHandlerTest.java
@@ -1,13 +1,13 @@
-package org.astraea.web;
+package org.astraea.app.web;
 
 import java.util.Map;
 import java.util.NoSuchElementException;
 import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
-import org.astraea.admin.Admin;
-import org.astraea.common.Utils;
-import org.astraea.service.RequireBrokerCluster;
+import org.astraea.app.admin.Admin;
+import org.astraea.app.common.Utils;
+import org.astraea.app.service.RequireBrokerCluster;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
diff --git a/app/src/test/java/org/astraea/web/WebServiceTest.java b/app/src/test/java/org/astraea/app/web/WebServiceTest.java
similarity index 81%
rename from app/src/test/java/org/astraea/web/WebServiceTest.java
rename to app/src/test/java/org/astraea/app/web/WebServiceTest.java
index 403c4ee9..452e36f4 100644
--- a/app/src/test/java/org/astraea/web/WebServiceTest.java
+++ b/app/src/test/java/org/astraea/app/web/WebServiceTest.java
@@ -1,5 +1,6 @@
-package org.astraea.web;
+package org.astraea.app.web;
 
+import org.astraea.app.argument.Argument;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
@@ -8,7 +9,7 @@ public class WebServiceTest {
   @Test
   void testArgument() {
     var argument =
-        org.astraea.argument.Argument.parse(
+        Argument.parse(
             new WebService.Argument(),
             new String[] {"--bootstrap.servers", "localhost", "--port", "65535"});
     Assertions.assertEquals("localhost", argument.bootstrapServers());