Restart main function of a java server [duplicate] - java

This question already has answers here:
cannot make a static reference to the non-static field
(7 answers)
Closed 5 years ago.
I'm working on my first Server/Client Project in Java. It's still very Basic and I was able to Exchange some data between the Server and the Client program.
Now I facing Trouble to reconnect once the Client has terminated the Connection.
I'm comfing from Visual Basic where I just would have had a timer and a boolean, checking if a Connection was established or not and eventually reset the socket.
I tried something similar in Java by Setting up a Start method and a Restart method and just checking in a Loop what's the Status of the boolean.
Unfortunately, eclipse keeps giving me the message that I cannot make a static reference to a non-static field. Now I'm totally lost.
Here's the server's code which works fine once but cannot be restarted.
package ComplexChatServer;
public class MainRoutine {
public Boolean boIsRunning;
public ConnectionHandlerS chsEins;
public Boolean boConnected = false;
public String strText;
public void StartRunning() {
boIsRunning = true;
chsEins = new ConnectionHandlerS();
chsEins.SocketListener();
}
public void ContinueRunning() {
boConnected = chsEins.getClientStatus();
if (boConnected == true) {
//System.out.println("Connected");
strText = null;
strText = chsEins.ReadInput();
if (strText != null && strText.isEmpty() == false) {
System.out.println("Loop");
System.out.println(strText);
strText = "";
boIsRunning = true;
}
else if (strText.equalsIgnoreCase("+++END+++")) {
boIsRunning = false;
System.exit(0);
}
}
else {
//System.out.println("Not connected");
}
}
public static void main (String [] args) {
int intRun;
while (true) {
if (boIsRunning = true) {
intRun = 1;
}
else {
intRun = 0;
}
switch (intRun) {
case 0:
StartRunning();
break;
case 1:
ContinueRunning();
break;
}
}
}
}

You can not make a static call to a non-static member. A static member in Java is a member that belongs to a class itself; not belonging to its objects. So you either have to instantiate a MainRoutine object and call it's methods or turn your existing methods into static ones to be able to call them from your already static main method; depending on what you want to achieve.
Besides that, conventionally Java community uses camel casing when naming methods and variables. Please check the syntactic and logical correction below:
public static void main (String [] args) {
MainRoutine routine = new MainRoutine();
while(true) {
if(boIsRunning) {
routine.continueRunning();
} else {
routine.startRunning();
}
}
}
Also as #Bill Horvath stated in his comment, notice that you're actually exiting the process rather than restarting it.

Related

System.out mysteriously disappears, although the code/line executes

Okay so I have tested this code on java 8, 11, and 14, they all have the same result.
This is bad practice and an unrealistic scenario, but I would like to understand the JVM internals that causes this to happen.
If you run this code you will notice that everything except the print part itself of system.out.println inside if execute.
At some point with a slightly different java version I managed to get it to print by changing "play" too volatile, but even that doesn't work now.
Please at least test the code before claiming it is simply deadlocking the variables or using the cache, it is not, the if executes and everything inside it works except the print part itself.
public class Main {
public static void main(String[] args) {
TestClass t = new TestClass();
System.out.println("Starting test");
new MyRunnable(t).start();
while (true)
t.testUpdate(System.currentTimeMillis());
}
}
public class MyRunnable extends Thread {
private TestClass t;
public MyRunnable(TestClass t) {
this.t = t;
}
#Override
public void run() {
try {
Thread.sleep(500L);
t.setPlay(true);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class TestClass {
private boolean play = false;
private long lastUpdate = 0;
private long updateRate = 2000;
private boolean hasSysoBeenHit = false;
public void testUpdate(long callTime) {
System.out.println(play);
System.out.println((callTime-lastUpdate));
if (this.play && ((callTime-lastUpdate) >= updateRate)) {
System.out.println("Updating! " + (hasSysoBeenHit = true));
this.lastUpdate = callTime;
}
System.out.println("hasbeenhit? " + hasSysoBeenHit);
}
public void setPlay(boolean t) {
System.out.println("Starting game...");
this.play = t;
}
}
Your code is suffering from a data race on the TestClass.play field: there are 2 threads accessing this field and at least one of them does a write. This is already indicated by #aerus.
If you make the field volatile, the data race gets removed. Look for the volatile variable rule in the Java Memory model.
I would also move the logic for the play checking to the begin of the testUpdate method:
public void testUpdate(long callTime) {
if(!play)return;
...

Creating array of methods returning boolean and iterating through for-each loop

Okay so I have a batch of methods returning boolean values of true/false.
private void saveChangesOnEditButtonActionPerformed(java.awt.event.ActionEvent evt) {
updateMainTabsAccess();
updateUserPaymentTabPermissions();
updateUserRegistrationTabPermissions();
updateUserStudentsTabPermissions();
updateUserFacultyTabPermissions();
updateUserHomePermissions(); //saves any update made on existing user settings/permissions
updateUserInformation(); // sasve any update made on existing user information such as username
}
I would like to know if it's possible for me to check each of the methods' return value through a for-each loop.
I'm thinking of creating a private boolean isUpdateSuccessful() method.
Say like,
private boolean isUpdateSuccessful(){
Boolean a = updateMainTabsAccess();
Boolean b = updateUserPaymentTabPermissions();
//........so on....
Boolean result = (a && b &&...)
return result;
}
Problem is, I don't know if it's possible to put them in an arraylist or component array like
ArrayList<Boolean> listOfMethods = new ArrayList<Boolean>(method1,method2..);
So that I can then check each through a for-each loop
for(Boolean b:listOfMethods){
Boolean successful=true;
successful = (successful && b)
}
My questions are:
1.) How do I extract the return values of these methods and use the methods to initialize the Arraylist.
2.) Using for-each loop, is there any possibility of what I'm trying to do? I none, then what do you suggest I do?
I'd appreciate any answer or suggestion. I simply want to check if every method was successful. I thought of using ?1:0:
Thanks in advance.
If I am you, I would do this. Just a sample code:
private void saveChangesOnEditButtonActionPerformed(java.awt.event.ActionEvent evt) {
if (updateMainTabsAccess()) {
if (updateUserPaymentTabPermissions()) {
if (updateUserRegistrationTabPermissions()) {
...
} else {
// error on update registration
}
} else {
// error on update payment
}
}
With the above style:
You don't execute other methods when the before one fails.
Can have detailed error messages for each error.
You need not to main a collection and iteration.
Why not use a Stream to check the results:
Stream.<Boolean>of(updateMainTabsAccess(),
updateUserPaymentTabPermissions(),
updateUserRegistrationTabPermissions(),
updateUserStudentsTabPermissions(),
updateUserFacultyTabPermissions(),
updateUserHomePermissions(),
updateUserInformation()).allMatch(b -> b);
this way you get rid of short circuit evaluation and also don't need to create method references for each method.
method references
List<Supplier<Boolean>> methods = Arrays.asList(this::updateMainTabsAccess,
this::updateUserPaymentTabPermissions,
...
);
for (Supplier<Boolean> supplier : methods) {
boolean methodResult = supplier.get();
...
}
This can hardly be considered an improvement though...
this will find all method in side your class which is return Boolean after automatically invoke method one by one and store response to successful variable
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
public class Test {
public static void main(String[] args) {
Test test = new Test();
Class c = test.getClass();
boolean successful = true;
for (Method method : c.getDeclaredMethods()) {
if (method.getReturnType().toString().equals("boolean")) {
try {
String mname = method.getName();
Object o = method.invoke(test, null);
System.out.format("%s() returned %b%n", mname, (Boolean) o);
successful = successful && (Boolean) o;
} catch (Exception e) {
e.printStackTrace();
}
}
}
System.out.println("final answer : " + successful);
}
public boolean a() {
return true;
}
public boolean b() {
return false;
}
public boolean c() {
return false;
}
}
Hope its help to you.
If you want every method to be executed and check if every method scucceded you could simply write
boolean success = updateMainTabsAccess() &
updateUserPaymentTabPermissions() &
updateUserRegistrationTabPermissions() &
updateUserStudentsTabPermissions() &
updateUserFacultyTabPermissions() &
updateUserHomePermissions() &
updateUserInformation();
You have already received some answers.
Fabian's is a good one if you are using java 8.
But to answer directly your points
1.) How do I extract the return values of these methods and use the methods to initialize the Arraylist.
ArrayList<Boolean> resultsList = new ArrayList<Boolean>();
resultsList.add(updateMainTabsAccess());
...
2.) Using for-each loop, is there any possibility of what I'm trying to do? I none, then what do you suggest I do?
boolean res = true;
for (Boolean singleResult : resultsList) {
res = res && singleResult;
}
Here is the old style way to acheive your goal when Lambdas weren't introduced by Java 8.
public class TestMethodsListCall {
public abstract class Checker {
public abstract boolean check();
}
public static void main(String[] args) {
new TestMethodsListCall();
}
public TestMethodsListCall() {
final TestMethodsListCall that = this;
List<Checker> checkers = Arrays.asList( //
new Checker() { public boolean check() { return that.methodA(); } }, //
new Checker() { public boolean check() { return that.methodB(); } } //
// , ...
);
boolean res = true;
for (Checker c : checkers) {
res = res & c.check();
if (!res) {
// Break, display some message or all together
}
}
}
public boolean methodA() {
return true;
}
public boolean methodB() {
return false;
}
}

Strange behaviour of a while-loop [duplicate]

This question already has an answer here:
Loop doesn't see value changed by other thread without a print statement
(1 answer)
Closed 7 years ago.
I am currently testing various ways of getting user-input. Today I was testing with the OnClosing(), which seem to work. My problem is that if I don't put anything in the while() - loop, it doesn't work. Its easier to show with code:
public MyClass() {
String myPassword= new Password().getpw();
}
ok. This is how I'm getting the string.
public class Password {
private boolean goon = true;
private JPasswordField jpassword = new JPasswordField ();
public Password() {
JFrame f = new JFrame("Type your password here, get it by closing the frame");
f.getContentPane().add(jpassword);
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
goon = false;
}
}
);
f.setSize(400,65);
f.show();
}
public String getpw() {
while (goon);
return new String(jpassword.getPassword());
}
}
This doesn't work unless I put something random in the while()-loop.. let me show you. This way it works
public String getpw() {
while (goon) {
System.out.println("");
}
return new String(jpassword.getPassword());
}
Why is it not working with an empty loop?
I found the answer after a lot of searching.
This happens because the code beneth the loop is "unreachable", because the loop loops nothing (only uses processor-capasity).
My loop can be illustrated the same way like this:
public String getpw() {
while (goon) {
doNothing();
}
return new String(jpassword.getPassword());
}
private void doNothing() { }
This is a horrible way of doing a loop, but if you absolutely need to do the loop. Make sure the loop actually does something.
This is still a horrible way of doing it, but I'll make an example:
public String getpw() {
String s = "";
while (goon) {
s += "";
}
return new String(jpassword.getPassword());
}
Now the loop actually does something, but its not recommended. I would use another aproach to this

Integer value doesn't change after assignment in function

I just got simple problem, but it seems that I cant find a solution for it. Well the following code is part of open-source project, but this part is written by me from scratch.
Well, everything inside this "script" works well without problems except of one thing,
the int variable CB_State doesn't change after calling StartParticipation() method:
import java.util.Calendar;
import java.util.logging.Logger;
import com.l2jserver.gameserver.Announcements;
import com.l2jserver.gameserver.ThreadPoolManager;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.network.serverpackets.NpcHtmlMessage;
public final class CastleBattle
{
private static Logger _log = Logger.getLogger("CastleBattle");
private static String htm_path = "data/scripts/l2dc/CastleBattle/";
public static int CB_State = 1; // 0 - Disabled, 1 - Not running, 2 - Participation start, 3 - Participation end, 4 - Running, 5 - Event ended
public CastleBattle()
{
CB_Init();
}
// Initialize Engine
private static void CB_Init()
{
if (CB_State == 1)
{
SetStartTime();
}
}
// Event Loop
public static void SetStartTime()
{
Calendar _nextTime = Calendar.getInstance();
int _m = _nextTime.get(Calendar.MINUTE);
int x = 1;
while (_m > 5)
{
_m -= 5;
x++;
}
_nextTime.set(Calendar.MINUTE, x * 5);
ThreadPoolManager.getInstance().scheduleGeneral(new CastleBattleLoop(), _nextTime.getTimeInMillis() - System.currentTimeMillis());
}
// Allow players to participate in the event
public static void StartParticipation()
{
CB_State = 2;
Announcements.getInstance().announceToAll("Castle Battle participation has started.");
_log.info("Castle Battle participation has started.");
}
// Player requests to join event via NPC
public static void CB_bypass(String _cmd, L2PcInstance _player)
{
if (_cmd.startsWith("InitHtmlRequest"))
{
if (CB_State == 0)
{
NpcHtmlMessage _html = new NpcHtmlMessage(0);
_html.setFile("", htm_path + "CB_Disabled.htm");
_player.sendPacket(_html);
}
if (CB_State == 1)
{
NpcHtmlMessage _html = new NpcHtmlMessage(0);
_html.setFile("", htm_path + "CB_NotRunning.htm");
_player.sendPacket(_html);
}
if (CB_State == 2)
{
NpcHtmlMessage _html = new NpcHtmlMessage(0);
_html.setFile("", htm_path + "CB_Participate.htm");
_player.sendPacket(_html);
}
}
}
public static void main(String[] args)
{
_log.info("# Castle Battle Engine #");
_log.info("Author : HyperByter");
_log.info("Version : Beta");
_log.info("Version : 3.7.2013");
new CastleBattle();
}
}
class CastleBattleLoop implements Runnable
{
#Override
public void run()
{
if (CastleBattle.CB_State == 1)
{
CastleBattle.StartParticipation();
}
}
}
So any suggestions how to fix this problem?
The method StartParticipation() is probably never called:
main() calls the constructor of CastleBattle
The CastleBattle constructor calls CB_Init()
CB_Init() calls SetStartTime()
SetStartTime() invokes this line:
ThreadPoolManager.getInstance().scheduleGeneral(new CastleBattleLoop(), _nextTime.getTimeInMillis() - System.currentTimeMillis());
after some whacky and indecipherable arithmetic on _nextTime, it's likely that the schedule interval is either very large, or perhaps negative, either of which may cause the Runnable CastleBattleLoop to never be started, in which case StartParticipation() would never be called.
I don't know what ThreadPoolManager does with strange input, but I would start by debugging what value is being passed into the scheduleGeneral() method and read the javadoc to see what effect such a value would have.
The class at the bottom is called CastleBattleLoop , but it does not contain anything loopy, so StartParticipation() gets called only once (if CB_State is 1 at that moment).
You should add something like
while(running){
if (CastleBattle.CB_State == 1)
{
CastleBattle.StartParticipation();
}
Thread.sleep(100);
}
StartParticipation() is being called inside a thread.
Check if you are trying to figure out its value even before actual change occurs.
[Not sure how are you figuring out the value of "CastleBattle.CB_State" in later part of the code]

Load a class using reflection and edit the variables during runtime [duplicate]

Okay, so I have a java file which is loading another class and I want the java file to be able to edit and read variables from the class which is running.
For example:
I have a button which when pressed it sets a variable (This is the class file). I want the java file which is loading this class to be able to see the new value of the variable read it, set it and do whatever is needed. And I want the new value which is set to show up on the running java class.
This is what I have tried so far but when I try to edit the values like getting baseX it doesn't show up on the running class. Also, the baseX value should change when I do stuff on the running class but the stuff is not printed to the screen when I change them. It's as if reflection can't read stuff on runtime. So what does?
Class c = Class.forName("Client");
for (Method m : c.getMethods()) {
if (m.getName().contentEquals("main")) {
Object[] passedArgs = { args };
m.invoke(null, passedArgs);
}
}
Object instance = c.newInstance();
Field baseX = c.getField("baseX");
Field loggedIn = c.getField("loggedIn");
boolean gotValues = false;
while(!gotValues) {
boolean loggedin = loggedIn.getBoolean(instance);
if(loggedin) {
System.out.println(baseX.get(instance));
} else {
System.out.println(loggedin);
loggedIn.setBoolean(instance, true);
}
}
Also yeah getter/setter methods would work if they worked on runtime and I could make it so that when button x is pressed variable y changes on screen. What is a java bean? Also what if I wanted to just invoke a method and not get a value? Or what if I wanted to add my own methods/code?
Try this:
public class Client {
public Object baseX = new Object();
public boolean loggedIn;
}
-----
public class Main {
public static void main(String[] args) throws Exception {
Class c = Class.forName("Client");
/*for (Method m : c.getMethods()) {
if (m.getName().contentEquals("main")) {
Object[] passedArgs = {args};
m.invoke(null, passedArgs);
}
}*/
Object instance = c.newInstance();
Field baseX = c.getField("baseX");
Field loggedIn = c.getField("loggedIn");
boolean gotValues = false;
//while (!gotValues) {
boolean loggedin = loggedIn.getBoolean(instance);
if (loggedin) {
System.out.println("Logged in!");
System.out.println(baseX.get(instance));
}
else {
System.out.println("NOT Logged in!");
System.out.println(loggedin);
loggedIn.setBoolean(instance, true);
System.out.println(loggedIn.getBoolean(instance));
}
//}
}
}

Categories

Resources