Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
The MUMPSorceress
Jan 6, 2012


^SHTPSTS

Gary’s Answer

Volmarias posted:

Would Autovalue be helpful?

it's not *quite* what I need as the functions in need of generation are specific to our internals but it's similar enough to what I want to do that I can use it as a starting point for hacking together something. Thanks!

Adbot
ADBOT LOVES YOU

M31
Jun 12, 2012
If AutoValue or Immutables doesn't do what you want, then you can create a custom annotation processor.

Jabor
Jul 16, 2010

#1 Loser at SpaceChem
Based on the current usage that's being described, refitting everything to use immutable value types is probably a bit out of scope.

That said, you can probably write your own annotation processor to do this. The big trick to annotation processors is that they can't modify the class with the annotation - instead, you can generate a new class based on the annotations that you see. This is, for example, why AutoValue has you write an abstract class, and then it will generate an impl class that implements all those abstract methods. The other big trick is that lots of stuff really hates working with generated code, which is why AutoValue hides virtually everything behind the non-generated abstract class that you wrote.

It shouldn't be too hard to write something similar, where you define an abstract class with abstract getters, abstract setters, and concrete implementations of one-off methods, and then generate a class with all the implementations. If you want to not have to write definitions for both the getter and setter, it gets sightly more annoying.

The MUMPSorceress
Jan 6, 2012


^SHTPSTS

Gary’s Answer

Jabor posted:

Based on the current usage that's being described, refitting everything to use immutable value types is probably a bit out of scope.

That said, you can probably write your own annotation processor to do this. The big trick to annotation processors is that they can't modify the class with the annotation - instead, you can generate a new class based on the annotations that you see. This is, for example, why AutoValue has you write an abstract class, and then it will generate an impl class that implements all those abstract methods. The other big trick is that lots of stuff really hates working with generated code, which is why AutoValue hides virtually everything behind the non-generated abstract class that you wrote.

It shouldn't be too hard to write something similar, where you define an abstract class with abstract getters, abstract setters, and concrete implementations of one-off methods, and then generate a class with all the implementations. If you want to not have to write definitions for both the getter and setter, it gets sightly more annoying.

this is a big part of it too. the getters and setters are annoying enough that I've considered at times just making these things public fields. however I think being able to just declare the abstract definitions of the boilerplate functions does get us a decent improvement.

My Rhythmic Crotch
Jan 13, 2011

Is there a "best" Redis client for Java? I'm using Jedis and having extremely weird behavior (hangs, timeouts??? No exceptions thrown so I'm not really sure) when doing a bunch of hsets and hgets.

To the best of my knowledge I'm doing what you're supposed to do... using JedisPool, getting the jedis object and closing the connection when done each time. Then it just goes to poo poo after a few calls. Sigh.

*Edit... I think I got it. The Jedis object is not thread safe and somehow all the exceptions were getting swallowed that would have clued me in.

My Rhythmic Crotch fucked around with this message at 19:58 on Oct 28, 2018

hooah
Feb 6, 2006
WTF?
I'm starting an EE project on my own, and am learning that even the bare-bones blueprint at work does a bunch of poo poo so I don't have to worry about it. The problem I'm currently fighting with is a transitive dependency on objenesis:
"java.lang.NoClassDefFoundError: org/objenesis/ObjenesisStd"

I started with
pre:
testCompile 'org.mockito:mockito-all:1.10.19'
and also have tried
pre:
testCompile 'org.mockito:mockito-all:2.0.2-beta'
I also have the objenesis dependency:
pre:
testCompile 'org.objenesis:objenesis:2.2'
but I still can't get past this drat error. What the gently caress's my issue?

Janitor Prime
Jan 22, 2004

PC LOAD LETTER

What da fuck does that mean

Fun Shoe
Check which jars are on the classpath you're trying to run with. Those dependencies are marked as testCompile so it will only be used when running test classes with the test classpath. Your IDE should set and use the test classpath when you run a class that's in the Test packages.

The MUMPSorceress
Jan 6, 2012


^SHTPSTS

Gary’s Answer
OK I'm trying to do something a little hare brained but I promise in the irl context it makes sense and isn't dumb.

Basically, I want a couple methods on my abstract class to be able to check the fields of a subclass and do something with their values I'd a particular annotation is present. Here's some code outlining what I'm thinking

Java code:

public abstract class abstractThingDoer {
public Collection getThings() {
List things = new ArrayList<>();
//I want to loop over fields of an implementing
//class here and, if the @IsAThing annotation is present
//add its value to the the list
return things;
}
}

public class thingDoer extends abstractThingDoer {
@IsAThing
private Thing thing1;
@IsAThing
private Thing thing2;

//blah blah random other stuff
}

I can get the fields of the subclass by adding an abstract getFields function that the subclass has to implement, but I don't see any way to get the values of the fields at runtime.

The way we accomplish things right now involves a lot of abstract methods whose implementation is basically boilerplate other than pointing them at the right fields and I'm trying to cut that down.

My previous idea of code generation didn't turn out to be feasible in our environment.

Is what I'm looking to do possible?

CPColin
Sep 9, 2003

Big ol' smile.
That's all very possible, in the magical world of reflection. You can do this.getClass() up in your abstract class, get the fields from there, figure out which ones have the annotation, and get their values. It shouldn't be too gross or fragile.

The MUMPSorceress
Jan 6, 2012


^SHTPSTS

Gary’s Answer

CPColin posted:

That's all very possible, in the magical world of reflection. You can do this.getClass() up in your abstract class, get the fields from there, figure out which ones have the annotation, and get their values. It shouldn't be too gross or fragile.

I think if you call that from the superclass you'll only get the superclass fields. At least that's what Google tells me.

CPColin
Sep 9, 2003

Big ol' smile.

jit bull transpile posted:

I think if you call that from the superclass you'll only get the superclass fields. At least that's what Google tells me.

this.getClass().getDeclaredFields() might work, if getFields() doesn't. I always have to tinker to get my reflection logic right. You'll probably have to call setAccessible(true) on each of the Field objects, too.

Pedestrian Xing
Jul 19, 2007

Commons FieldUtils is great for any reflection stuff.

Jabor
Jul 16, 2010

#1 Loser at SpaceChem

jit bull transpile posted:

I think if you call that from the superclass you'll only get the superclass fields. At least that's what Google tells me.

If you call getFields() on the Class object for the superclass, then yeah, that's what you'll get.

But calling getClass() on the instance will give you the Class object for the specific subclass, which will have the fields that you want.

Note that if you want to get all the fields (including the ones that aren't visible to you), you'll need to use getDeclaredFields instead, and potentially walk up the chain of superclasses doing it repeatedly.

The MUMPSorceress
Jan 6, 2012


^SHTPSTS

Gary’s Answer

Jabor posted:

If you call getFields() on the Class object for the superclass, then yeah, that's what you'll get.

But calling getClass() on the instance will give you the Class object for the specific subclass, which will have the fields that you want.

Note that if you want to get all the fields (including the ones that aren't visible to you), you'll need to use getDeclaredFields instead, and potentially walk up the chain of superclasses doing it repeatedly.

The fields I want will always be in the final derivative class so that won't be a problem.

How do I access the values inside those fields though? All the functions I found required an object as an argument. Does just passing in this in the superclass suffice?

Jabor
Jul 16, 2010

#1 Loser at SpaceChem
Yeah, you just pass in this as the instance.

The Field objects themselves aren't specific to an instance, there's one for all instances of that class. So if you want to get the actual value of the field via reflection, you need to pass in the object you want to get the field value from.

The MUMPSorceress
Jan 6, 2012


^SHTPSTS

Gary’s Answer

Jabor posted:

Yeah, you just pass in this as the instance.

The Field objects themselves aren't specific to an instance, there's one for all instances of that class. So if you want to get the actual value of the field via reflection, you need to pass in the object you want to get the field value from.

Thank you. This is so much clearer than the Java trail documents or any of the garbled English tutorials I could find. I swear I'm not dumb!

1337JiveTurkey
Feb 17, 2005

Also because the reflective methods are slow as hell, best practice is to do the reflection one for the class rather than once for each instance and reuse the same reflective object once configured. Because of this, you don't necessarily want all the reflection in the superclass so you can call it for each instance but stick it in a helper object. Look up the helper object for the class from a map, creating it if it doesn't exist and then reuse it as often as necessary.

Also if you're using a remotely recent version of the JVM the java.lang.invoke package allows for much more performant accessing the values of fields once you've reflectively found them once for the class. I haven't touched it in years but there's effectively a method handle equivalent to reflectively accessing a field that skips a lot of unnecessary permissions checks after the initial check and gets close to non-reflective access speed.

evilentity
Jun 25, 2010
Im making a two player multiplayer game and i have one annoying problem on the server side.

The match processing on the server is very lightweight and i want to support as many concurrent matches as possible.
Its 1v1, so 2 clients and 1 arena. Turn based, few actions per second at best.

So whats the best way to server many arenas with few threads? A thread waiting doing nothing and eating memory is probably not great when it could be used to process other arena.
Currently i have a Queue<Queue<Action>> (not really) and a worker thread that takes a Queue<Action> processes few actions and sticks it back to the queue, if there are any left.
When action is added to inner queue, that queue is added to outer one. The goal of that nested queue crap is to disallow actions for single arena to be processed out of order by multiple worker threads.
Does that make any sense whatsoever? Probably not...

Never did server stuff, all my assumptions are probably wrong :shrug:

Spring on Tomcat, if thats relevant.

evilentity fucked around with this message at 19:44 on Nov 3, 2018

brap
Aug 23, 2004

Grimey Drawer
Have you considered using Executors.newSingleThreadExecutor() for your worker and just queueing up stuff you want it to do?

Sagacity
May 2, 2003
Hopefully my epitaph will be funnier than my custom title.

evilentity posted:

Spring on Tomcat, if thats relevant.
It's worth taking a look at recently released Kotlin 1.3 which has coroutines. It will allow you to do this kind of processing using a fairly natural syntax.

Nothing you couldn't do in plain Java but if you're a bit unsure on how to implement it, Kotlin is worth a look, if only to avoid shooting yourself in the foot using low-level concurrency primitives.

evilentity
Jun 25, 2010
Im already using Executors.newFixedThreadPool for the worker(s). Single thread would make this a lot simpler, but on the other hand its single thread. If this ever gets any actual users, i will find out if single thread would be enough or not. Odds are it would be enough, but wheres the fun in that?

I did play with kotlin before and it was quite fun, but throwing it in with unfamiliar server and spring stuff would just complicate things even more. Perhaps in next project!

baka kaba
Jul 19, 2003

PLEASE ASK ME, THE SELF-PROFESSED NO #1 PAUL CATTERMOLE FAN IN THE SOMETHING AWFUL S-CLUB 7 MEGATHREAD, TO NAME A SINGLE SONG BY HIS EXCELLENT NU-METAL SIDE PROJECT, SKUA, AND IF I CAN'T PLEASE TELL ME TO
EAT SHIT

#newCachedThreadPool might be a better fit, since it'll grow and shrink as threads are needed or left idle. Or build your own with ThreadPoolExecutor if you want more control!

I'm assuming you mean you have a queue of games, each represented by a list of pending actions? So each thread gets a game, processes the first few actions, then kicks the game to the back of the queue (if there's anything left to do). So the game processing is done in steps, each step happens entirely on one thread, and the next step only happens when the current one has finished (so you never have more than 1 thread processing a given game at any time)

You could look into work-stealing algorithms if you like, but your code has to be written in a way that makes that useful

Sindai
Jan 24, 2007
i want to achieve immortality through not dying
My first thought is to assign each game to a specific thread when it's created according to which thread has the fewest active games, have a separate action queue for each thread, and then whenever an action comes in for a given game toss it onto that thread's queue. This doesn't guarantee perfect load balancing but as long as your networking also guarantees order (ie you aren't using raw UDP) you're safe from race conditions.

The MUMPSorceress
Jan 6, 2012


^SHTPSTS

Gary’s Answer
Just FYI my crazy annotation stuff worked first try so thanks yall!

Objective Action
Jun 10, 2007



jit bull transpile posted:

Just FYI my crazy annotation stuff worked first try so thanks yall!

I'm glad your reflection solution got it sorted for you. Just for reading material there are two other options I've used over the years under similar circumstances. One is the JSR 269: Pluggable Annotation Processing API that was already discussed earlier. This lets you write, but not edit, new classes at compile time and has decent documentation from Oracle. If you ever want to go that route I very strongly recommend JavaPoet from Square as it makes it infinitely easier to write correct generated source.

The second, darker, way is to use the Element javax package (or the corresponding Eclipse compiler packages) and cast them to an AST representation and edit the node tree inline. This is a way to jam generated code into existing classes but relies on building on a Sun/Eclipse compiler implementation. Project Lombok and some AOP frameworks do this under the covers for instance.

Objective Action fucked around with this message at 03:22 on Nov 9, 2018

Hekk
Oct 12, 2012

'smeper fi

I am hot garbage at programming and trying to get better. I've been working on this for 15 or 20 hours and I can't for the life of me figure out a solution.

I am 4 weeks into an 8 week introductory programming class. My assignment is to create a Java class called Guitar with several methods.

Pastebin of my Java Class

With that class created I then need to run some tests and get the correct outputs. One of the things I need to be able to do is create 3 Guitars with different parameters (String Count, Length, Manufacturer, and Color). I can't get past trying to change the color. I've read and read and looked all over and short of cheating by buying something off of one of those cheat sites, I have no idea how to proceed.

My Test Guitar Program

I am super frustrated because I feel like this is something simple I should be grokking but I just can't make the connection. Can anyone please point me in the right direction? All I need to be able to do is change the guitar color and manufacturer to create 3 unique instances of a Guitar that I can then conducts tests with.

Hekk fucked around with this message at 21:09 on Nov 16, 2018

CPColin
Sep 9, 2003

Big ol' smile.

quote:


//I can create new guitars with default info but I am having difficulty changing the manufacturer and color.
//If I try to change the info by typing new Guitar(10,24,"Les Paul", "blue"); I get errors I can't figure out


At first glance, you would need to pass Color.blue here, not "blue", which is a String value. I also noticed in your test class, you're changing the color of guitar2, but printing the color of guitar1.

Beyond that, what sort of errors or incorrect output are you seeing?

Hekk
Oct 12, 2012

'smeper fi

CPColin posted:

At first glance, you would need to pass Color.blue here, not "blue", which is a String value. I also noticed in your test class, you're changing the color of guitar2, but printing the color of guitar1.

Beyond that, what sort of errors or incorrect output are you seeing?

Yeah sorry I have modified those lines several dozens of times now trying to get something correct. The "guitar2.changeColor(Color.black);" line returns an error when I try to compile and my IDE tells me to import Guitar.Color which doesn't fix the issue.

smiling giraffe
Nov 12, 2015
Your enum is defined within the Guitar class, so its going to need to be

guitar2.changeColor(Guitar.Color.black);

Hekk
Oct 12, 2012

'smeper fi

smiling giraffe posted:

Your enum is defined within the Guitar class, so its going to need to be

guitar2.changeColor(Guitar.Color.black);

If I could kiss you through this screen I would. Thanks much! I have what I need now. I knew I was close.

The MUMPSorceress
Jan 6, 2012


^SHTPSTS

Gary’s Answer

Nostalgia4Ass posted:

If I could kiss you through this screen I would. Thanks much! I have what I need now. I knew I was close.

Fwiw if you had listened to your compiler errors and actually put "import Guitar.Color" at the top of your file it would have worked too

You should read about namespaces

Hekk
Oct 12, 2012

'smeper fi

jit bull transpile posted:

Fwiw if you had listened to your compiler errors and actually put "import Guitar.Color" at the top of your file it would have worked too

You should read about namespaces

I appreciate the feedback. I tried to import Guitar.Color but I may or may not have done things correctly. I think I just needed to walk away for a bit because frustration was getting the best of me. I've spent the last 4 days working on homework that should have taken a single evening and now I have two days to do my relational database project.

In hindsight, I need to stagger my classes to where I only have one time consuming course at a time because my work/exercise/family/school balance is kind of out of whack right now and panic set in for a few hours.

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope
PIT mutation testing owns. (http://pitest.org/)

This is not a question, just a statement of fact.

Keetron
Sep 26, 2008

Check out my enormous testicles in my TFLC log!

Wheany posted:

PIT mutation testing owns. (http://pitest.org/)

This is not a question, just a statement of fact.

Could be, but I have troubles understanding the output when having run the tools.

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope

Keetron posted:

Could be, but I have troubles understanding the output when having run the tools.

Yes, some of the mutation reports could be more clear, especially when you have several on one row, but things like "removed call to ClassName::methodName" are pretty self-explanatory.

oh no computer
May 27, 2003

I'm trying to get back into Java coding and to this end I'm making a clone of the game 2048. I have a working console version and I'm just trying to build a simple GUI for it, but it's been years since I've done any GUI stuff and it's not working properly.

I have a class GameTile that extends JPanel and whose paintComponent method that just draws a String (which is the value of the tile) and a thin rectangular border. I have a GameBoard which extends JPanel and is set up to use a 4x4 GridLayout, this panel is then added to a JFrame's contentPane.

GameBoard stores the state of the board as a 2D GameTile array where each element either points to a GameTile object or null. The paintComponent method of the GameBoard is below:
code:
public void paintComponent(Graphics g)
{
    removeAll(); // clear the panel of the previously added tiles
    for (GameTile[] row : board)
    {
        for (GameTile tile : row)
        {
            if (tile != null)
                add(tile);
            else
                add(new JPanel());
        }
    }
}
i.e. each non-null GameTile object in the array is added to the GameBoard panel, each null reference just adds a dummy JPanel in order to skip to the next cell of the GridLayout. This correctly draws the board when the program starts up, showing the two initial tiles placed in a random location on the 4x4 grid.

GameBoard also implements KeyListener to listen for up, down, left or right arrow keys, and calls the move method for that direction before repainting:
code:
public void keyPressed(KeyEvent e)
{
    switch (e.getKeyCode())
    {
        case 37: // LEFT KEY
        {
            board.move(0);
            break;
        }
        case 38: // UP KEY
        {
            board.move(1);
            break;
        }
.... etc etc
    }
    repaint();
}
But as you press the keys, the only tiles showing on the screen are the two initial ones, no new tiles are added. If you make sufficient moves that cause one of the initial tiles to merge with another tile, the value updates accordingly but the location of that tile never changes. However if you minimise or resize the frame, it updates to show the correct status of the board.

I know that this means that the call to repaint() above isn't doing what I think it's doing and I should be calling repaint() somewhere else but I really can't think where. Since resize and minimise fix it I thought that maybe I should be repainting the JFrame, but I tried adding a manual call to that but it didn't help.


edit: revalidate() you loving idiot

oh no computer fucked around with this message at 16:33 on Feb 20, 2019

CPColin
Sep 9, 2003

Big ol' smile.
Looks like you got it. I was going to guess that changing the layout of your board while you were trying to paint it was causing a bunch of updates to stomp all over each other.

John F Bennett
Jan 30, 2013

I always wear my wedding ring. It's my trademark.

Probably shouldn't use Swing to make games or anything else for that matter.

Try Libgdx for a great gamedev framework in Java.

oh no computer
May 27, 2003

Yeah I'm not trying to make games only getting some general practice in with GUI stuff.

Although on a related note I haven't really coded in Java since version 5 - is Swing completely dead now? If so I'm guessing JavaFX has replaced it? I guess I should probably look into learning that?

Adbot
ADBOT LOVES YOU

Volguus
Mar 3, 2009

oh no computer posted:

Yeah I'm not trying to make games only getting some general practice in with GUI stuff.

Although on a related note I haven't really coded in Java since version 5 - is Swing completely dead now? If so I'm guessing JavaFX has replaced it? I guess I should probably look into learning that?

Yes, JavaFX is the new thing. Swing, while dead, won't be removed from the JDK for probably a long time.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply