v0.2.35.XXX
application.yml
plain
java -jar .\DrawAndChatApp-0.2.35.2-SNAPSHOT.jar --spring.config.additional-location=.\application.yml
DrawAndChatApp - Session init & control Page
will open upNewUseSend - Host
application.yml
cpy.rf.ntt.drc:
det-DisableReceiveNetworkMsg-Kafka: false
kafka:
bootstrap.servers: "localhost:9092" # @edit_this[base on your Config]
profiles.active: "plain, Enable_ReceiveNetworkMsg"
ClearAllMsg_InKafkaTopic
NewUseSend - Host
On Guest side - Click the Button ReceiveNetworkMsg - Guest
db_drawandchat_01
/ db_drawandchat_02
) &Drc_NodeEvent_All-Host
& Drc_NodeEvent_All-Guest
)com.redfrog.note.database.DbThreadHelper.clear_TabelRows_db01()
public static final String queryStrf_GetAllTableName = "SELECT table_name FROM information_schema.tables WHERE table_schema = '%s';";
public static final String queryStrf_RemoveAllRowInATable = "TRUNCATE TABLE %s;";
public static final String tableName_hibernate_sequence = "hibernate_sequence";
@Transactional(value = "txm_01")
public List<String> clear_TabelRows_db01() {
Query query_GetAllTableName = em_01.createNativeQuery(String.format(queryStrf_GetAllTableName, DbName.db_drawandchat_01));
List<String> resultList_AllTableName = query_GetAllTableName.getResultList();
System.out.println(">> clear_TabelRows_db01() :: " + DbOccupation.DbName.db_drawandchat_01 + " :: " + Thread.currentThread().getName() + " :: " + resultList_AllTableName + " :: " + em_01);
if (resultList_AllTableName.size() > 5) {
String msg = "Seems deleting a lot of tables es rows? Is this Sql correct? :: numTable=" + resultList_AllTableName.size();
System.out.println(msg);
throw new Error(msg);
}
for (String tableName : resultList_AllTableName) {
if (!tableName.equals(tableName_hibernate_sequence)) {
Query query_RemoveAllRowInATable = em_01.createNativeQuery(String.format(queryStrf_RemoveAllRowInATable, tableName));
query_RemoveAllRowInATable.executeUpdate();
}
else {
System.out.println("Do nothing with table :: " + tableName_hibernate_sequence);
}
}
return resultList_AllTableName;
}
com.redfrog.note.util.KafkaUtil.clear_AllMsg_debug(KafkaConfig)
public static void clear_AllMsg_debug(KafkaConfig kafkaConfig) {
String msg = "The way clear_AllMsg() implemented is very bad -- delete Records in a Kafka topic is possible, "
+ "\n" + "but doesnt have a good API in Java (-- missing sufficient info to get Access to the Partition & the Offset of the Message).";
System.out.println(msg);
System.err.println(msg);
Consumer<String, ? extends Object> kConsumer_AnyRecord = new KafkaConsumer<>(kafkaConfig.kProp_Consumer);
kConsumer_AnyRecord.subscribe(Arrays.asList(kafkaConfig.kTopicName_Send_NodeEvent_All, kafkaConfig.kTopicName_Receive_NodeEvent_All));
while (true) {
try {
ConsumerRecords<String, ? extends Object> consumerRecords = kConsumer_AnyRecord.poll(Duration.ofMillis(1200));
if (consumerRecords.isEmpty()) {
System.out.println("Seems all msg drained.");
kConsumer_AnyRecord.close();
break;
}
for (ConsumerRecord<String, ? extends Object> consumerRecord : consumerRecords) {
System.out.println("Draining :: " + consumerRecord); //
}
} catch (WakeupException e) {
System.out.println("Seems we are shutting down :: " + e);
kConsumer_AnyRecord.close();
}
}
}
mysqldump -u USERNAME -pPASSWORD DBNAME > /path/to/location/backup.sqlsee https://stackoverflow.com/questions/4283168/how-can-i-backup-a-mysql-database-from-java
mysql -u USERNAME -pPASSWORD --database DBNAME < /path/to/location/backup.sql
application.yml
spring: config: activate: on-profile: "Enable_LoadSaveFile | prod" ds-mysql-01: driver-class-name: com.mysql.cj.jdbc.Driver hibernate.dialect: org.hibernate.dialect.MySQL5Dialect jdbc-url: jdbc:mysql://localhost:3306/db_drawandchat_01 # @edit_this[base on your Config] # database name is hardcoded (seems); (other type of database (not mysql) may not be supported); password: mysql # @edit_this[base on your Config] username: root # @edit_this[base on your Config] ds-mysql-02: # db02 is mainly for debugging driver-class-name: com.mysql.cj.jdbc.Driver hibernate.dialect: org.hibernate.dialect.MySQL5Dialect jdbc-url: jdbc:mysql://localhost:3306/db_drawandchat_02 # @edit_this[^] password: mysql # @edit_this[^] # password & username should be same as db01 username: root # @edit_this[^] cpy.rf.ntt.drc: det-DisableLoadSaveFile-Mysql: false loadSaveFile: pathStr-drcFileSave: "H:\\DrawAndChatApp_db" # @edit_this[base on your Config] # default path for save & load the file pathStr-mysqldump: "C:\\Program Files\\MySQL\\MySQL Server 8.0\\bin\\mysqldump.exe" # @edit_this[base on your Config] # path to mysqldump pathStr-mysql: "C:\\Program Files\\MySQL\\MySQL Server 8.0\\bin\\mysql.exe" # @edit_this[base on your Config] # path to mysql # you can just put `mysql` if your env var is properly set (seems)
profiles.active: "plain, Enable_LoadSaveFile"
NewUseSend - Host
Editing File Window
em.persist()
is slow & may still be going in the background (just for Saving your file)10s ~ 40s+ ~ ?s
to finish all persist."Auto Close When Sql persist is Done "
."Force Close Right Now "
.SaveFile
(in DrawAndChatApp - Session init & control Page
)Session init Page
(close the App)Force use given db
db_drawandchat_01
)ClearAllTableRows_InGivenDb
public static final String TextWarn_OverwriteOrAppendDb =
"""
[Warning: 80% - @datalost] det_ExistDataIn_EntityGeneral != 0; for db :: %s
Detected Existing Old Data in this Db.
"""
+ Text_ClearAllTableRows_InGivenDb +
"""
Basing on your selection on det_AllowDbOverwriteOrAppend :: %s
If true:
-> New Data will be Appended to the Existing Old Data - for New session / Receive session.
-> Existing Old Data will be Cleared, New Data will be Written to an empty/cleared database - for Load session.
If false:
-> Throw an Error, Session Abort, No data are cleared or written.
""";
LoadSaveFile - Host
application.yml
profiles.active: "Enable_ReceiveNetworkMsg, Enable_LoadSaveFile"
NewUseSend - Host
/ReceiveNetworkMsg - Guest
Editing File Window
SaveFile
(in DrawAndChatApp - Session init & control Page
)Session init Page
(close the App)Force use given db
db_drawandchat_01
db_drawandchat_02
db_drawandchat_02
,ClearAllTableRows_InGivenDb
LoadSaveFile - Host
/ReceiveNetworkMsg - Guest
DrawAndChatVm
is the central -- of this ProjectNodeSender_ConvertWrapper
& NodeSender_EventAnnouncer
are the central -- of DataCommunicationNodeSig
& NodeEvent
are the backbone data structure -- of all the Node & NodeEvent (all the business objects)SessionManager
& WindowSession
is the central -- for the management & linkage across all the classes in the Project[NewUseSend, ReceiveNetworkMsg, LoadSaveFile]
DrawAndChatAppSessionInit
is the first contact when you start the AppDrawAndChatAppSessionInit
SessionManager
WindowSession
DbOccupation
to the SessionKafkaConfig
DrawAndChatVm
NodeSender_ConvertWrapper
& NodeReceiver_EventListener
DrawAndChatVm_ReceiveNetworkMsg
& DrawAndChatVm_LoadSaveFile
are just variations of DrawAndChatVm
DrawAndChatVm
DrawAndChatVm
-- deal with NewUseSend session (-- actually backbone of all Sessions)DrawAndChatVm_ReceiveNetworkMsg
-- deal with ReceiveNetworkMsg sessionDrawAndChatVm_LoadSaveFile
-- deal with LoadSaveFile sessionNodeSender_ConvertWrapper
& NodeReceiver_ConvertHandler
are the bridges between DrawAndChatVm
& MessageQueue/DatabaseDrawAndChatVm
NodeSender_ConvertWrapper
> NodeSender_EventAnnouncer
NodeReceiver_EventListener
> NodeReceiver_ConvertHandler
NodeSender_ConvertWrapper
JavafxNode
to NodeSig
/ associate / find them in NodeSigManager
NodeCreatorAndConvertor
JavafxNode
to/from NodeSig
NodeSender_EventAnnouncer
NodeEvent
NodeEvent
DbThreadHelper
MultipleDbSpringConfig
SerializationUtilsSerializer
& SerializationUtilsDeserializer
NodeReceiver_EventListener
NodeEvent
NodeEvent
NodeReceiver_ConvertHandler
NodeEvent
This App is built using a mechanism - Event Sourcing
-- every single action is sent by MsgBroker & persist into Database -- as an Event.
Functionality | Hotkey | Description | Activated When | * |
---|---|---|---|---|
Freehand Drawing in Canvas | LButton (drag) | Focus on Canvas | ||
create a Panel (+ a TextArea) | ^n | (nest supported) | Focus on Panel / Root Panel | |
move a Node | ^!LButton (drag) | (You need to click on the PaneWrap of the Node) | Focus on PaneWrap of the Node | |
remove a Node | delete | (You need to click on the PaneWrap of the Node) | Focus on PaneWrap of the Node | |
focus on a Node | LButton | (You need to click on the PaneWrap of the Node) | Global | |
draw an Arrow to link 2 Nodes | ^LButton RButton (to Cancel) | click on Node AA to Start & click on Node BB to End (note: its very thin & hard to be clicked to Focus on) | Focus on Panel / PaneWrap of the Node | |
undo | ^z | (undo when focusing in TextArea is diff) | Focus on Panel / Root Panel | |
redo | ^+z | Focus on Panel / Root Panel | ||
clear Drawing in Canvas | RButton (drag) | Focus on Canvas | ||
create a TextArea | ^+b | Focus on Panel / Root Panel | ||
create a Canvas | ^m | Focus on Panel / Root Panel | ||
type on TextArea (bi-dir) | (Tab to focus on) | Focus on TextArea | ||
resize a Node | ^!LButton (drag, on the Resize_Handler) | Focus on Resize_Handler of the Node | ||
move Layer of a Node | PgUp PgDn Home End | (Note: the Layer of the Canvas in the Background can be moved too) | Focus on PaneWrap of the Node | |
zoom a Node | ^WheelUp ^WheelDown F1 | F1 reset the zoom | Focus on PaneWrap of the Node | |
move the Background (Root Panel) | ^!MButton (drag) F4 | F4 reset the position | Global | |
move the MiniMap | ^!LButton (drag) | Focus on the MiniMap | ||
create a IndexCircle | ^i ^1 ^2 ^3 ^4 ^5 | ^i increment index by 1 ^1 reset index to 1 | Focus on Panel / Root Panel | |
change Text on IndexCircle | (Tab & Type the Text) | Focus on the IndexCircle | ||
copy a Node | Not supported | |||
cut a Node | ^x | Focus on PaneWrap of the Node | ||
paste a Node | ^v | cut a Node & Focus on Panel / Root Panel | ||
change Pen Color of Canvas | !0 !1 !2 !3 !4 !5 !6 !7 !8 | !0 is the original blue color (Note: if the Canvas is not focused (to receive hotkey), you can Tab to focus on it) | Focus on Canvas | |
static
public
@Scope("prototype")
(but not sure how well it will do).@Inheritance(strategy = InheritanceType.JOINED)
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@GeneratedValue(strategy = GenerationType.SEQUENCE)
@OneToOne(cascade = { CascadeType.PERSIST })
,Serializable
Interface.Protobuf
will be considered.plain
is designed specifically for this case).application.yml
is ready to use).java -jar .\DrawAndChatApp-0.2.35.2-SNAPSHOT.jar --spring.config.additional-location=.\application.yml