I am developing my bot for discord using Java and JDA API. Before that I asked a similar question, but I ran into another problem.
From this line the problems started :
final Member MentionedMem = event.getMessage().getMentionedMembers().get(0);
Thanks to https://stackoverflow.com/users/10630900/minn for answering the previous question in which he explained to me that this line is causing the error :
java.lang.IndexOutOfBoundsException: Index 0 out of bounds for length 0
For some reason or other it raises an error.
I was trying to find an answer to why this command does not work. The only thing I know is that this command returns an empty array args. Because of this, I cannot finish the bot, that is, I cannot check whether a member can kick others and can't make the main block of code kick members.
How can I fix this error and / or write the rest of the code?
Sorry for my English and many thanks to you.
Some code :
public class KickComm extends ListenerAdapter {
public void onGuildMessageReceived(GuildMessageReceivedEvent event) {
String[] message = event
.getMessage()
.getContentRaw()
.split(" ");
// final Member target = event.getMessage().getMentionedMembers().get(0); ERROR CUZ I DONT NOW WHY
final Member SelfMember = event
.getGuild()
.getSelfMember();
if(message[0].equalsIgnoreCase(Main.prefix + "kick"))
{
if (message.length < 2) {
EmbedBuilder NoUser = new EmbedBuilder();
NoUser.setColor(0xff3923);
NoUser.setTitle("\uD83D\uDD34You need to add a <#username> and <reason>");
NoUser.setFooter("Usage: " + Main.prefix + "kick <#username> <reason>.",
Objects
.requireNonNull(event.getMember())
.getUser()
.getAvatarUrl());
event
.getChannel()
.sendMessage(NoUser.build())
.queue();
NoUser.clear();
} else if (message.length < 3) {
EmbedBuilder NoReason = new EmbedBuilder();
NoReason.setColor(0xff3923);
NoReason.setTitle("\uD83D\uDD34You need to add a <reason>.");
NoReason.setFooter("Usage: " + Main.prefix + "kick <#username> <reason>.",
Objects
.requireNonNull(event.getMember())
.getUser()
.getAvatarUrl());
event
.getChannel()
.sendMessage(NoReason.build())
.queue();
NoReason.clear();
} else if(!SelfMember.hasPermission(Permission.KICK_MEMBERS)) {
EmbedBuilder NoPermission = new EmbedBuilder();
NoPermission.setColor(0xff3923);
NoPermission.setTitle("\uD83D\uDD34You don't have permission to use this command.");
NoPermission.setFooter("Usage: " + Main.prefix + "kick <#username> <reason>.",
Objects
.requireNonNull(event.getMember())
.getUser()
.getAvatarUrl());
event
.getChannel()
.sendMessage(NoPermission.build())
.queue();
NoPermission.clear();
} else if(!Objects.requireNonNull(event.getMember()).hasPermission(Permission.KICK_MEMBERS) || !event.getMember().canInteract(target)) { //Example, don't works
EmbedBuilder NoPermission = new EmbedBuilder();
NoPermission.setColor(0xff3923);
NoPermission.setTitle("\uD83D\uDD34You don't have permission to use this command.");
NoPermission.setFooter("Usage: " + Main.prefix + "kick <#username> <reason>.",
Objects
.requireNonNull(event.getMember())
.getUser()
.getAvatarUrl());
event
.getChannel()
.sendMessage(NoPermission.build())
.queue();
NoPermission.clear();
}
}
}
}
UPD: Please, if you downgrade, then point out the mistakes that I made, and not just downgrade it because you wanted to. I want to correct mistakes, not ruin your mood
It seems like you didn't quite get the problems in your code.
final Member target = event.getMessage().getMentionedMembers().get(0);
This will throw an IndexOutOfBoundsException if your message doesn't include a mentioned member. Because in this case the list of getMentionedMembers() is empty. There is no object to access. get(0) can't get anything.
In order to fix this you have to check first if the list is empty or if the length is zero as Minn already proposed. If it is you can display a message stating, that they need to add an #username.
Cleaning up your code and restructuring it accordingly would help a lot I suppose. Please go over it and make sure to always check, if the needed data exists in the first place and if you really need it. Some things are only needed for a small number of cases, calling them on every message / command is not good practice.
For example, at the moment your bot tries to get the first mentioned member from EVERY message that is sent. This isn't necessary hence you only need it in case it is the kick command.
By the way, the SelfMember is the bot itself. In your code you are telling the user that they don't have the permission although the bot (and not necessarily the user) might lack it which could be confusing.
I didn't see it earlier: Your bot is receiving its own messages as well. You might want to check, if the author of a message is your / a bot before continuing.
In the end I would advice you to always try to understand the answer or advice that is given to you. Asking another question for the same problem isn't going to help you nor does it cast a good light on you and your attempt to learn.
User mentionedUser = event.getMessage().getMentionedMembers().get(0).getUser();
If someone still needs it...
The issue, for some reason, was that you used Member instead of User.
Futhermore, you must use .getUser() to really get the user you want.
Related
My intentions are to ask the user to write down some code in a TextArea, then see if that code compiles, and if it does, print out the results to another TextArea, which acts like a console.
Edit:Solving this via online compilers is the priority.
To accomplish this, I've tried using online compilers (i.e. compilerjava.net) and used the library HtmlUnit, but the library came in with a lot of errors, especially when reading the JavaScript code and returned me pages of 'warnings' that increase the compile & run time for about 20 seconds. I will leave the code below with explanations if anyone has intentions about trying to fix it.
I've also tried using the JavaCompiler interface, which did succeed in compiling, but under the conditions that I have provided the exact location of the .java file, which is something I have to create using the information I get from the TextArea. So again, a dead end.
I decided to come back to online compilers, since if I can manage to just return the data from the compiled program, I am set. The only issue is I haven't yet found an online compiler that allows a user to access its fields via Java code ( since its something too specific). I would appreciate any help on this if anyone can provide a way to send and retrieve data from an online compiler.
Here is the code using the HtmlUnit library, on the site 'compilerjava.net'. It is so close to working that the only 2 issues I have is that,
1) Run-time is too long.
2) I cannot access the console output of the code. Reasoning is that, when you hit 'compile', the output text-area's text turns into "executing". After a few seconds, it turns into the output of the code. When I try to access it, the data I retrieve is always "executing" and not the desired output. Here is the code;
public class Test {
public static void main(String[] args) {
try {
// Prevents the program to print thousands of warning codes.
java.util.logging.Logger.getLogger("com.gargoylesoftware").setLevel(java.util.logging.Level.OFF);
java.util.logging.Logger.getLogger("org.apache.http").setLevel(java.util.logging.Level.OFF);
// Initializes the web client and yet again stops some warning codes.
WebClient webClient = new WebClient( BrowserVersion.CHROME);
webClient.getOptions().setThrowExceptionOnFailingStatusCode( false);
webClient.getOptions().setThrowExceptionOnScriptError( false);
webClient.getOptions().setJavaScriptEnabled( true);
webClient.getOptions().setCssEnabled( true);
// Gets the html page, which is the online compiler I'm using.
HtmlPage page = webClient.getPage("https://www.compilejava.net/");
// Succesfully finds the form which has the required buttons etc.
List<HtmlForm> forms = page.getForms();
HtmlForm form = forms.get( 0);
// Finds the textarea which will hold the code.
HtmlTextArea textArea = form.getTextAreaByName( "code");
// Finds the textarea which will hold the result of the compilation.
HtmlTextArea resultArea = page.getHtmlElementById( "execsout");
// Finds the compile button.
HtmlButtonInput button = form.getInputByName( "compile");
System.out.println( button.getValueAttribute());
// Simple code to run.
textArea.setText( "public class HelloWorld\n" +
"{\n" +
" // arguments are passed using the text field below this editor\n" +
" public static void main(String[] args)\n" +
" {\n" +
" System.out.print( \"Hello\");\n" +
" }\n" +
"}");
// Compiles.
button.click();
// Result of the compilation.
System.out.println( resultArea.getText());
} catch ( Exception e) {
e.printStackTrace();
}
}
}
As I said, this final code System.out.println( resultArea.getText()); prints out "executing", which implies that I have succeeded in pressing the compile button on the webpage via code.
So after this long wall of text, I'm either looking for a way to fix the code I presented, which is so darn close to my answer but not quite, or just an entirely different solution to the problem I presented at the beginning.
P.S. Maven is the last hope.
I am using the tutorial here for pushing data and consuming, data from Azure Service Bus. When I run the example the second time, I get back an error PUT https://asbtest.servicebus.windows.net/TestQueue?api-version=2012-08 returned a response status of 409 Conflict, which is way of saying you have already a configuration with that name, so do not create it another time. Most probably, this is the guilty code
Configuration config =
ServiceBusConfiguration.configureWithWrapAuthentication(
"HowToSample",
"your_service_bus_owner",
"your_service_bus_key",
".servicebus.windows.net",
"-sb.accesscontrol.windows.net/WRAPv0.9");
ServiceBusContract service = ServiceBusService.create(config);
QueueInfo queueInfo = new QueueInfo("TestQueue");
That is recalling create() is causing the problem, I would guess. But all methods in com.microsoft.windowsazure.services.serviceBus.ServiceBusService from http://dl.windowsazure.com/javadoc/ are only create, and I am unable to find a method like
ServiceBusContract service = A_class_that_finds_existing_bus_contract.find(config);
Am I thinking the wrong way, or is there another way out. Any pointers are appreciated.
EDIT:
I realized my code example for what I was asking was config, not service bus contract. Updated it, to reflect so.
Turns out I was wrong. The create() function in ServiceBusService does not throw any exception, as I gathered from Javadocs. Also, you can create the service bus contracts multiple times, as it being only a connection. The exception arises, when you attempt to create a queue with a name that already exists. That is this line.
String path = "TestQueue";
QueueInfo queueInfo = new QueueInfo(path);
To overcome this, you can go this way.
import com.microsoft.windowsazure.services.serviceBus.Util;
...
...
Iterable<QueueInfo> iqnf = Util.iterateQueues(service);
boolean queue_created = false;
for( QueueInfo qi : iqnf )
{
if( path.toLowerCase().equals( qi.getPath() ))
{
System.out.println(" Queue already exists. Do not create one.");
queue_created = true;
}
}
if ( !queue_created ) {
service.createQueue(queueInfo);
}
Hope, this helps anybody who may be stuck on create conflicts for queue on Azure.
EDIT: Even after I got the path code, my code refused to work. Turns out there is another caveat. Azure makes all queue names in lower case. I have edited the code to use toLower() for this work around.
I upvoted Soham's Question and Answer. I did not know about lowercase though I have not verified it. It did confirm the problem I am having right now as well.
The way #Soham has addressed it is good but not good for large ServicebUs where we may have tons of Queues it's added overhead to iterate it. The only way is to catch the ServiceException which is very generic and ignore that Exception.
Example:
QueueInfo queueInfo = new QueueInfo(queName);
try {
CreateQueueResult qr = service.createQueue(queueInfo);
} catch (ServiceException e) {
//Silently ignore for now.
}
The right way would be for the Azure library to extend the ServiceException and throw "ConcflictException" for e.g. which is present in httpStatusCode of ServiceException but unfortunately it's set to Private.
Since it is not We would have to extend the ServiceException and override the httpStatusCode setter.
Again, not the best way but the library can improve if we list as feedback on their Github issues.
Note: ServiceBus is still in preview phase.
I was wondering if there is a way to dump the state of all local variables when there is an exception, to get a better idea of the state of the environment that caused the exception. Below the variable idsToDump is unknown at run time and I want to find out the state at which value in the collection is causing the NPE.
Example:
public static void main(String[] args) {
HashMap<Integer, String> employees = new HashMap<Integer, String>();
employees.put(1, "James");
Integer[] idsToDump = new Integer[] { 1, 2, 3 };
for (Integer employeeId : idsToDump) {
String name = employees.get(employeeId).toLowerCase();
System.out.println(name + " is employee number: " + employeeId);
}
}
output:
james is employee number: 1
Exception in thread "main" java.lang.NullPointerException
Question:
Is there some JVM argument that I can pass to dump information about the current state of the local variables? ie we get
java.lang.NullPointerException
and (this is the part I'm after)
values: employeeId=2
I want to be able to do this on a client site, so no access to Eclipse or debugging tools, looking for just JVM arguments, can't make code changes either. I have looked through them but couldn't really find anything. In the meantime I'll keep searching there too ;)
I came across a commercial product that does this by simply using a startup -agentlib JVM agent param. I haven't used it yet but intend on giving it a try as it looks very promising.
https://www.takipi.com/product
Anyone have experience with this product?
Given all your restrictions, I can't recommend anything else apart from jdb. Fire that bad boy up and start stepping through the client code line by line. I know you said no debugging tools, but unless they are a JRE only environment you should have jdb installed already.
The easiest thing to do is to run this code in a debugger and step through it. If you can't debug the code then you can use a try/catch block and set employeeId outside of this like:
int debugEmployeeId = -1;
try {
Integer[] idsToDump = new Integer[] { 1, 2, 3 };
for (Integer employeeId : idsToDump) {
debugEmployeeId = employeeId;
...
} catch (Exception e) {
throw new Exception("Missing employeeId = " + Integer.toString(debugEmployeeId));
}
Although you have mentioned that you are not able to do any code changes, here a hint for the case that code changes are still possible: A handy tool to get some more information about the exception is the method "printStackTrace" of the thrown exception object. You may want to use something like this.
try {
...
}
catch ( Exception e ) {
System.out.println( "Exception occured! Reason: " + e.printStackTrace() );
}
Your best option, afaik, is the old manual way: use some sort of logging (be it Log4J, or just stdout), and to explicitly record the variables you're interested in via a catch block.
Like Thomas, I don't know of any current method that can dump variables. However, I believe you want to do so to aid you in your debugging. Here are some simple methods which I use to debug my code using just the console:
1.Learn to read the stacktrace when the exception occurs. It gives you a lot of information on what could be potentially causing the exception. If the particular line that the stacktrace is pointing to doesn't seem to have anything wrong, track back the code and see if it was a prior object that is causing the exception. For example (using some sample code and methods):
Book book = null;
Bookshelf bookshelf = new Bookshelf();
bookshelf.add(book);
bookshelf.getBooks();
Something like that will cause the NPE stacktrace to point to bookshelf, but actually it is book that is causing the NPE.
2.Print out the variables that you suspect are causing the NPE.
for (Integer employeeId : idsToDump) {
System.out.println(employeeId);
String name = employees.get(employeeId).toLowerCase();
System.out.println(name + " is employee number: " + employeeId);
}
Your output will be:
1
2
And then you'll know that 2 is causing the NPE.
3.Comment out the suspicious code and systematically uncomment out the code until the exception occurs, or vice-versa.
Although you may find it tedious and frustrating at times, it really does help in your foundation because with enough practice, you'll soon be able to intuitively spot where the error usually occurs (and hence spend less time on future debugging).
You can see my posted code here. My original problem was more or less solved but now I'm running into the problem described in the question title. Here's the problem: After I enter a command on the client side of any given client, I can't enter additional commands. The first command will work fine (minus /exit; haven't quite figured out how that should work yet), just can't do anything after that. For example, I can do /register (sign in) but after that nothing else. I can go into another instance of Client and list all the current users with /list as well (works), but again, after that I cannot enter additional commands - the console will not take them after the first one. Any idea what may be happening to cause this?
Here is about where I'm referring to (Code in its entirety):
while((keyboardInput = keyboardInputScanner.nextLine()) != null){
System.out.println("Input '" + keyboardInput + "' read on client side.");
if(keyboardInput.equals("/exit")){
socketOut.println("/exit");
socketOut.close();
socketIn.close();
serverSocket.close();
}else{
socketOut.println(keyboardInput);
}
while((serverInput = socketIn.readLine()) != null){
System.out.println(serverInput);
}
}
I'm relatively sure it's something to do with not breaking out of the inner while loop, but I don't know any way around it. If I put that while loop outside of the keyboard input loop, I'll never get anything back from the server.
I think the problem is here:
while((serverInput = socketIn.readLine()) != null){
System.out.println(serverInput);
}
This will loop indefinitely (well, until the socket is closed at the other end). You therefore never get to the second iteration of the outer loop.
You might want to either limit the response to one line, or have some other mechanism for the server to let the client know when to stop reading from socketIn (e.g. send an empty line at the end of every server response and have the client break out of the inner loop when it sees that).
I am having problems with my converter program not accepting the value the user inputs. Everything seems so right but the result is always as if the user entered nothing. If anyone can just point me in the right direction I would greatly appreciate it!
my project consists of 2 files (1 midlet and 1 class).
code was too long to post on this forum so I uploaded the zip.
Edit hosted here now should be cleaner: removed
I can't really narrow it down to a small piece of code because it could be any number of things which I have already tried. I know its asking quite a bit but the code isn't insanely long. I'd be extremely grateful if anyone could take a look.
edit 2: the file seems to be trying to download an image... here is the code in another forum i posted in but got no answers.: http://www.codingforums.com/showthread.php?p=1024059#post1024059
edit 3: here is where I think the problem lies in the code:` public double customForm (String fName)
{
ui_form = new Form(fName);
ui_form.addCommand(Convert);
ui_form.addCommand(Back);
display.setCurrent(ui_form);
num = new TextField("Enter the number of units you would like to convert", "", MAX_CHARS, TextField.ANY);
ui_form.append(num);
ui_form.setCommandListener(this);
/***********************/
/* THIS IS NOT WORKING*/
// str = num.getString();
str = "The number is: " + num.getString();
try
{
numUnits = Double.parseDouble(str);
}
catch (NumberFormatException nfe)
{
}
finally
{
return numUnits;
}
//return str;
}
`
but you will probably need to look at the rest of the code to see where the problem lies. this is just the root i think
You cannot read the text field right after it has been added to a form. It looks like you assumed the num.getString() method to block until there's user input - this is not the case. User input is provided asynchronously, i.e. you should read the text field's content in response to a user command, somewhere in the commandAction() method (in your case when the Convert command has been issued by the user).
Handling user events asynchronously is a core pattern in GUI development. In this regard I recommend to read some example code for command handling in JavaME, for instance this or this.