EDIT: I've decided to remove the Minecraft tag. While this IS a Minecraft mod's code, the code I'm having trouble with has to do with functions within core Java, and not anything in Minecraft itself.
So, I posted a question last night about me writing a function of a Minecraft mod to allow us to implement our own capes and thanks to some of you I was able to get that working. I've crammed down the code from there and found a way to make it as small as possible while producing the same outcome. I've also found out how to read files directly from a download stream instead of copying the file. Great? Well, no. Now that I'm able to properly test everything and read my files, I've run into another problem. While everything works fine, it causes a lag spike of upwards to 2-4 seconds whenever my code is running. I've looked around and found issues about slow downloads, but nothing about the application completely freezing for a small period of time. Since this is run whenever a player first appears on-screen, this can get repetitive. I'm trying to fix the code and have rearranged it countless times in different ways and it just won't go away.
Here's the code. In short, it checks if the player has an official Mojang cape on their account. If they don't, then instead it runs my code to check if they have one of our custom capes, and exactly when this is run, is when the game has a lag spike. Note that if the player has a cape from Mojang my code is never run and I've tried disabling my code and just running the code that downloads their Mojang cape for use, so I know that part doesn't cause lag, it's specifically just my code. Even if they don't have a custom cape under my code it always causes lag. I can't think of why; the files are very small!
... While writing this, I decided to test something, and so I disabled the player.cloakUrl variable setting lines in my getCustomCapes method. Surely enough the lag still happened so I reckon the lag is caused by the lines that check if the player UUID matches one in the downloaded .txt files. I'm confident the lines of code that check and download from the .txt files are the culprits to the lag here. Note that I'm reading from streamed online files rather than saving them to the computer permanently since they don't need to. They're read every time this code is called and it needs to stay that way.
Without further ado here's the code.
EDIT: I've tried to add .close() commands to the streams with no success.
public static void getSkin(final GameProfile profile, EntityPlayer player) {
final Map<Type, MinecraftProfileTexture> map = Maps.<Type, MinecraftProfileTexture>newHashMap();
// (Here's where some skin-related code would be but I cut it out for easier reading,
// it has nothing to do with this situation so don't worry about that.)
if (map.containsKey(Type.CAPE))
{
MinecraftProfileTexture texture = (MinecraftProfileTexture)map.get(Type.CAPE);
player.cloakUrl = texture.getUrl();
return;
} else {
getCustomCapes(profile, player); //Commenting this fixes the lag, proving it's my code that causes it.
}
}
public static void getCustomCapes(final GameProfile profile, EntityPlayer player) {
InputStream staff;
InputStream contest;
try {
contest = new URL("https://www.dropbox.com/s/kvvkfk6emms3qg5/contest.txt?dl=1").openStream();
StringWriter contestUUIDs = new StringWriter();
IOUtils.copy(contest, contestUUIDs, StandardCharsets.UTF_8);
if (contestUUIDs.toString().contains(profile.getId().toString()))
{
player.cloakUrl = "https://www.dropbox.com/s/a4d3agty57sd4a8/contest.png?dl=1";
// Commenting out the above line doesn't seem to help any, as stated before.
return;
}
staff = new URL("https://www.dropbox.com/s/q6f4729i2zu02nz/staff.txt?dl=1").openStream();
StringWriter staffUUIDs = new StringWriter();
IOUtils.copy(staff, staffUUIDs, StandardCharsets.UTF_8);
if (staffUUIDs.toString().contains(profile.getId().toString()))
{
player.cloakUrl = "https://www.dropbox.com/s/42jn5r7fs6k5f4l/staff.png?dl=1";
// Commenting out the above line doesn't seem to help any, as stated before.
return;
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
What an old thread, huh? So, after getting a little more experience I decided to head back to this to say I've found the solution. Here's how I fixed it: Thread magic! ug_ suggested this to me a while ago it seems, but I simply didn't understand at the time. I used some methods to start a thread with special variables that set the player's properties when it's done, removing the lag. Also, I rewrote the way the cape .txts work to be a little more efficient. You may notice there's one file now, and that one controls everything instead of each list having its own file. Here's my code. First, the above get skin methods have been scraped out almost entirely, and I added a new one since creating a GameProfile sends requests to Mojang's API, causing a little bit of lag, so I made it so this thread can also generate profiles:
public static void getSkin(final GameProfile profile, EntityPlayer player) {
ThreadFetchSkins skinThread = new ThreadFetchSkins();
skinThread.start(player, profile, mc);
}
public static void getSkinFromUUIDAndName(UUID uuid, String username, EntityPlayer player) {
ThreadFetchSkins skinThread = new ThreadFetchSkins();
skinThread.start(uuid, username, player, mc);
}
And then, here's the thread.
public class ThreadFetchSkins extends Thread {
public static TreeMap<UUID, String> customCapes = new TreeMap<UUID, String>();
private EntityPlayer thePlayer;
private GameProfile theProfile;
private Minecraft mc;
private boolean createProfile = false;
private UUID id;
private String name;
public ThreadFetchSkins() {
setName("Cape data download thread");
setDaemon(true);
}
public void run() {
if(createProfile) {
theProfile = new GameProfile(id, name);
}
final Map<Type, MinecraftProfileTexture> map = Maps.<Type, MinecraftProfileTexture>newHashMap();
theProfile.getProperties().clear();
theProfile.getProperties().putAll(SkinManager.getProfileProperties(theProfile));
map.putAll(mc.sessionService.getTextures(theProfile, false));
//Removed "secure" textures grab
if (map.containsKey(Type.SKIN))
{
MinecraftProfileTexture texture = (MinecraftProfileTexture)map.get(Type.SKIN);
thePlayer.skinUrl = texture.getUrl();
String grab = texture.getMetadata("model");
// Currently returns null for steve skin
thePlayer.modelAlex = !(grab == null);
thePlayer.worldObj.obtainEntitySkin(thePlayer);
}
if (map.containsKey(Type.CAPE))
{
MinecraftProfileTexture texture = (MinecraftProfileTexture)map.get(Type.CAPE);
thePlayer.cloakUrl = texture.getUrl();
thePlayer.worldObj.obtainEntitySkin(thePlayer);
}
else {
grabCustomCapes();
}
}
public void grabCustomCapes() {
try {
URL capeDownload = new URL("https://www.dropbox.com/s/q6f4729i2zu02nz/capes.txt?dl=1");
String capeFolder = Minecraft.getMinecraftDir().getPath() + "/NFCCapes";
FileUtils.forceMkdir(new File(capeFolder));
FileUtils.copyURLToFile(capeDownload, new File(capeFolder + "/capes.txt"));
InputStream fileOS = new FileInputStream(capeFolder + "/capes.txt");
BufferedReader buf = new BufferedReader(new InputStreamReader(fileOS));
String line = buf.readLine();
customCapes.clear();
while(line != null) {
String[] data = line.split(";");
customCapes.put(UUID.fromString(data[1]), data[2]);
line = buf.readLine();
}
fileOS.close();
FileUtils.getFile(capeFolder).delete();
if(customCapes.get(theProfile.getId()) != null) {
thePlayer.cloakUrl = customCapes.get(theProfile.getId());
thePlayer.worldObj.obtainEntitySkin(thePlayer);
}
} catch (MalformedURLException e) {
e.printStackTrace();
return;
} catch (IOException e) {
e.printStackTrace();
return;
}
}
public void start(EntityPlayer player, final GameProfile profile, Minecraft minecraft) {
thePlayer = player;
theProfile = profile;
mc = minecraft;
super.start();
}
public void start(UUID uuid, String username, EntityPlayer player, Minecraft minecraft) {
id = uuid;
name = username;
thePlayer = player;
mc = minecraft;
createProfile = true;
super.start();
}
}
I want to load and render multiple objects to a gameworld using data from a class with a save/load functionality using (de)serialization, but i cant figure out how to properly reintroduce them to the program since they contain transient objects that are nessesary to render/display them.
The first time i run my program, it tries to load data from a txt file called 'Data.txt' that doesnt exist. The program creates a new Data.txt file, adds a Campfire object called 'campfire'to it and saves it. As long as the program runs it will be rendered to the screen (this part works fine). After closing the program and restarting it its supposed to check for the file, find it and load the ArrayList 'data' with the previously saved/serialized campfire object from it. Then it adds another Object of the same type to it and renders both of them. This part throws a NullPointerException in the render method of my Campfire class.
This is the Main class:
public class MainClass extends ApplicationAdapter{
public static SpriteBatch batch;
private Data data;
private Campfire campfire;
#Override
public void create () {
batch = new SpriteBatch();
data = new Data();
data.load();
campfire = new Campfire();
data.addCampfire(campfire);
System.out.println(data.getSize());
data.save();
}
#Override
public void render () {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
data.render(batch);
batch.end();
}
The class that loads all the files:
public class Data {
private String filename;
private ArrayList<Campfire> data;
public Data() {
data = new ArrayList<Campfire>();
filename = "Data.txt";
}
public void save(){
try {
FileOutputStream file = new FileOutputStream (filename);
ObjectOutputStream out = new ObjectOutputStream (file);
out.writeObject(data);
out.close();
file.close();
}catch (IOException e) {e.printStackTrace();}
}
public void load() {
try {
FileInputStream file = new FileInputStream (filename);
ObjectInputStream in = new ObjectInputStream(file);
data = (ArrayList<Campfire>)in.readObject();
in.close();
file.close();
}
catch (IOException io) {System.out.println("File not found.");}
catch (ClassNotFoundException ex) {System.out.println("Cant load from file.");}
}
public void addCampfire(Campfire object) {
data.add(object);
}
public void render(SpriteBatch batch) {
for(int i = 0;i < data.size(); i++) {
Campfire camp = data.get(i);
camp.render(batch);
//data.get(i).render(batch);
}
}
public Campfire get(int index) {
return data.get(index);
}
public void set(int index, Campfire object) {
data.set(index, object);
}
public int getSize() {
return data.size();
}
And this is the class that throws the NullPointerException in render():
public class Campfire implements Serializable{
private transient Texture img;
private int id;
public Campfire() {
img = new Texture("campfire.png");
}
public void render(SpriteBatch batch) {
batch.draw(img, 200,200, 2000,2000);
}
The reason for this is that the Texture 'img' is nonexistent since i need to use the transient keyword with it and therefore it will not be saved/loaded to/from the data file.
i need a different way to create objects based on the array list i am loading from. I cant work with the objects in the arrayList because they cant be rendered (the transient keyword has to be assigned to the Texture() object - its not serializable). I have watched plenty of tutorials and read a good amount on articles about this topic, but i cant find one that mentions how i can reintroduce the object so i can make use of its functions that rely on not (de)serializable parts of it.
So heres my question:
Is there a better way than my attempt (creating the object again and then assigning the deserialized values to it? I have no clue how to properly load and work with the 'data' ArrayList after the deserialization process and i am thankful for every advice on how to reintroduce them to the program.
Thanks in advance,
M
I would recommend not using java serialization for this. It can have advantages in terms of the size of its serialized format, but in my experience it is a little bit of a pain to work with. You have encountered this pain, because you cannot serialize that Texture object because it is not Serializable. You avoided the issue by marking it as transient, which is a mistake. There are probably workarounds for working with objects that you do not own - registering some handler, but tbh I do not know the details because I avoid it.
Instead, go for a nice friendly format like json. This will mean that your serialized data file will be a bit bigger, but, you can open it up and read it and see what you have saved.
And... libgdx comes with some tools for it. See their wiki page on usage here
There are alternatives - like googles gson library as well, but why not just stick with libgdx's tools - I have found them to be pretty solid.
Just an extra warning - if you are using some sort of code obfuscation/minimization tool in Android, you will need to configure that to not rename any object that you serialize, because it does rely on the package and object names for deserialization. It is also something to be aware of if you save a game state - then change the names/packages of your objects and then try to load that game state.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
The community reviewed whether to reopen this question 1 year ago and left it closed:
Original close reason(s) were not resolved
Improve this question
You can create various Java code templates in Eclipse via
Window > Preferences > Java > Editor > Templates
e.g.
sysout is expanded to:
System.out.println(${word_selection}${});${cursor}
You can activate this by typing sysout followed by CTRL+SPACE
What useful Java code templates do you currently use? Include the name and description of it and why it's awesome.
I am looking for an original/novel use of a template rather than a built-in existing feature.
Create Log4J logger
Get swt color from display
Syncexec - Eclipse Framework
Singleton Pattern/Enum Singleton Generation
Readfile
Const
Traceout
Format String
Comment Code Review
String format
Try Finally Lock
Message Format i18n and log
Equalsbuilder
Hashcodebuilder
Spring Object Injection
Create FileOutputStream
The following code templates will both create a logger and create the right imports, if needed.
SLF4J
${:import(org.slf4j.Logger,org.slf4j.LoggerFactory)}
private static final Logger LOG = LoggerFactory.getLogger(${enclosing_type}.class);
Log4J 2
${:import(org.apache.logging.log4j.LogManager,org.apache.logging.log4j.Logger)}
private static final Logger LOG = LogManager.getLogger(${enclosing_type}.class);
Log4J
${:import(org.apache.log4j.Logger)}
private static final Logger LOG = Logger.getLogger(${enclosing_type}.class);
Source.
JUL
${:import(java.util.logging.Logger)}
private static final Logger LOG = Logger.getLogger(${enclosing_type}.class.getName());
Some additional templates here: Link I -
Link II
I like this one:
readfile
${:import(java.io.BufferedReader,
java.io.FileNotFoundException,
java.io.FileReader,
java.io.IOException)}
BufferedReader in = null;
try {
in = new BufferedReader(new FileReader(${fileName}));
String line;
while ((line = in.readLine()) != null) {
${process}
}
}
catch (FileNotFoundException e) {
logger.error(e) ;
}
catch (IOException e) {
logger.error(e) ;
} finally {
if(in != null) in.close();
}
${cursor}
UPDATE: The Java 7 version of this template is:
${:import(java.nio.file.Files,
java.nio.file.Paths,
java.nio.charset.Charset,
java.io.IOException,
java.io.BufferedReader)}
try (BufferedReader in = Files.newBufferedReader(Paths.get(${fileName:var(String)}),
Charset.forName("UTF-8"))) {
String line = null;
while ((line = in.readLine()) != null) {
${cursor}
}
} catch (IOException e) {
// ${todo}: handle exception
}
Format a string
MessageFormat - surround the selection with a MessageFormat.
${:import(java.text.MessageFormat)}
MessageFormat.format(${word_selection}, ${cursor})
This lets me move a cursor to a string, expand the selection to the entire string (Shift-Alt-Up), then Ctrl-Space twice.
Lock the selection
lock - surround the selected lines with a try finally lock. Assume the presence of a lock variable.
${lock}.acquire();
try {
${line_selection}
${cursor}
} finally {
${lock}.release();
}
NB ${line_selection} templates show up in the Surround With menu (Alt-Shift-Z).
I know I am kicking a dead post, but wanted to share this for completion sake:
A correct version of singleton generation template, that overcomes the flawed double-checked locking design (discussed above and mentioned else where)
Singleton Creation Template:
Name this createsingleton
static enum Singleton {
INSTANCE;
private static final ${enclosing_type} singleton = new ${enclosing_type}();
public ${enclosing_type} getSingleton() {
return singleton;
}
}
${cursor}
To access singletons generated using above:
Singleton reference Template:
Name this getsingleton:
${type} ${newName} = ${type}.Singleton.INSTANCE.getSingleton();
Append code snippet to iterate over Map.entrySet():
Template:
${:import(java.util.Map.Entry)}
for (Entry<${keyType:argType(map, 0)}, ${valueType:argType(map, 1)}> ${entry} : ${map:var(java.util.Map)}.entrySet())
{
${keyType} ${key} = ${entry}.getKey();
${valueType} ${value} = ${entry}.getValue();
${cursor}
}
Generated Code:
for (Entry<String, String> entry : properties.entrySet())
{
String key = entry.getKey();
String value = entry.getValue();
|
}
For log, a helpful little ditty to add in the member variable.
private static Log log = LogFactory.getLog(${enclosing_type}.class);
Create a mock with Mockito (in "Java statements" context):
${:importStatic('org.mockito.Mockito.mock')}${Type} ${mockName} = mock(${Type}.class);
And in "Java type members":
${:import(org.mockito.Mock)}#Mock
${Type} ${mockName};
Mock a void method to throw an exception:
${:import(org.mockito.invocation.InvocationOnMock,org.mockito.stubbing.Answer)}
doThrow(${RuntimeException}.class).when(${mock:localVar}).${mockedMethod}(${args});
Mock a void method to do something:
${:import(org.mockito.invocation.InvocationOnMock,org.mockito.stubbing.Answer)}doAnswer(new Answer<Object>() {
public Object answer(InvocationOnMock invocation) throws Throwable {
Object arg1 = invocation.getArguments()[0];
return null;
}
}).when(${mock:localVar}).${mockedMethod}(${args});
Verify mocked method called exactly once:
${:importStatic(org.mockito.Mockito.verify,org.mockito.Mockito.times)}
verify(${mock:localVar}, times(1)).${mockMethod}(${args});
Verify mocked method is never invoked:
${:importStatic(org.mockito.Mockito.verify,org.mockito.Mockito.never)}verify(${mock:localVar}, never()).${mockMethod}(${args});
New linked list using Google Guava (and similar for hashset and hashmap):
${import:import(java.util.List,com.google.common.collect.Lists)}List<${T}> ${newName} = Lists.newLinkedList();
Also I use a huge template that generates a Test class. Here is a shortened fragment of it that everyone interested should customize:
package ${enclosing_package};
import org.junit.*;
import static org.junit.Assert.*;
import static org.hamcrest.Matchers.*;
import static org.mockito.Matchers.*;
import static org.mockito.Mockito.*;
import org.mockito.Mockito;
import org.slf4j.Logger;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.junit.runner.RunWith;
// TODO autogenerated test stub
#RunWith(MockitoJUnitRunner.class)
public class ${primary_type_name} {
#InjectMocks
protected ${testedType} ${testedInstance};
${cursor}
#Mock
protected Logger logger;
#Before
public void setup() throws Exception {
}
#Test
public void shouldXXX() throws Exception {
// given
// when
// TODO autogenerated method stub
// then
fail("Not implemented.");
}
}
// Here goes mockito+junit cheetsheet
Null Checks!
if( ${word_selection} != null ){
${cursor}
}
if( ${word_selection} == null ){
${cursor}
}
One of my beloved is foreach:
for (${iterable_type} ${iterable_element} : ${iterable}) {
${cursor}
}
And traceout, since I'm using it a lot for tracking:
System.out.println("${enclosing_type}.${enclosing_method}()");
I just thought about another one and have found it over the Internet some day, const:
private static final ${type} ${name} = new ${type} ${cursor};
A little tip on sysout -- I like to renamed it to "sop". Nothing else in the java libs starts with "sop" so you can quickly type "sop" and boom, it inserts.
Throw an IllegalArgumentException with variable in current scope (illarg):
throw new IllegalArgumentException(${var});
Better
throw new IllegalArgumentException("Invalid ${var} " + ${var});
Nothing fancy for code production - but quite useful for code reviews
I have my template coderev low/med/high do the following
/**
* Code Review: Low Importance
*
*
* TODO: Insert problem with code here
*
*/
And then in the Tasks view - will show me all of the code review comments I want to bring up during a meeting.
Some more templates here.
Includes:
Create a date object from a particular date
Create a new generic ArrayList
Logger setup
Log with specified level
Create a new generic HashMap
Iterate through a map, print the keys and values
Parse a time using SimpleDateFormat
Read a file line by line
Log and rethrow a caught exeption
Print execution time of a block of code
Create periodic Timer
Write a String to a file
slf4j Logging
${imp:import(org.slf4j.Logger,org.slf4j.LoggerFactory)}
private static final Logger LOGGER = LoggerFactory
.getLogger(${enclosing_type}.class);
Bean Property
private ${Type} ${property};
public ${Type} get${Property}() {
return ${property};
}
public void set${Property}(${Type} ${property}) {
${propertyChangeSupport}.firePropertyChange("${property}", this.${property}, this.${property} = ${property});
}
PropertyChangeSupport
private PropertyChangeSupport ${propertyChangeSupport} = new PropertyChangeSupport(this);${:import(java.beans.PropertyChangeSupport,java.beans.PropertyChangeListener)}
public void addPropertyChangeListener(PropertyChangeListener listener) {
${propertyChangeSupport}.addPropertyChangeListener(listener);
}
public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
${propertyChangeSupport}.addPropertyChangeListener(propertyName, listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
${propertyChangeSupport}.removePropertyChangeListener(listener);
}
public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {
${propertyChangeSupport}.removePropertyChangeListener(propertyName, listener);
}
Post Java 7, a great way to set up loggers which need (or prefer) static references to the enclosing class is to use the newly introduced MethodHandles API to get the runtime class in a static context.
An example snippet for SLF4J is:
private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
Aside from being a simple snippet in any IDE, it is also less brittle if you refactor certain functionality into another class because you won't accidentally carry the class name with it.
Invoke code on the GUI thread
I bind the following template to the shortcut slater to quickly dispatch code on the GUI thread.
${:import(javax.swing.SwingUtilities)}
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
${cursor}
}
});
When testing around with code I sometimes missed out on deleting some syso s. So I made myself a template called syt.
System.out.println(${word_selection}${});//${todo}:remove${cursor}
Before I compile I always check my TODOs and will never forget to delete a System.out again.
strf -> String.format("msg", args) pretty simple but saves a bit of typing.
String.format("${cursor}",)
Get an SWT color from current display:
Display.getCurrent().getSystemColor(SWT.COLOR_${cursor})
Suround with syncexec
PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable(){
public void run(){
${line_selection}${cursor}
}
});
Use the singleton design pattern:
/**
* The shared instance.
*/
private static ${enclosing_type} instance = new ${enclosing_type}();
/**
* Private constructor.
*/
private ${enclosing_type}() {
super();
}
/**
* Returns this shared instance.
*
* #returns The shared instance
*/
public static ${enclosing_type} getInstance() {
return instance;
}
And an equalsbuilder, hashcodebuilder adaptation:
${:import(org.apache.commons.lang.builder.EqualsBuilder,org.apache.commons.lang.builder.HashCodeBuilder)}
#Override
public boolean equals(Object obj) {
return EqualsBuilder.reflectionEquals(this, obj);
}
#Override
public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this);
}
The template for the logger declaration is great.
I also create linfo, ldebug, lwarn, lerror for the log levels that I use more often.
lerror:
logger.error(${word_selection}${});${cursor}
Create everything for an event
Since events are kinda a pain to create in Java--all those interfaces, methods, and stuff to write just for 1 event--I made a simple template to create everything needed for 1 event.
${:import(java.util.List, java.util.LinkedList, java.util.EventListener, java.util.EventObject)}
private final List<${eventname}Listener> ${eventname}Listeners = new LinkedList<${eventname}Listener>();
public final void add${eventname}Listener(${eventname}Listener listener)
{
synchronized(${eventname}Listeners) {
${eventname}Listeners.add(listener);
}
}
public final void remove${eventname}Listener(${eventname}Listener listener)
{
synchronized(${eventname}Listeners) {
${eventname}Listeners.remove(listener);
}
}
private void raise${eventname}Event(${eventname}Args args)
{
synchronized(${eventname}Listeners) {
for(${eventname}Listener listener : ${eventname}Listeners)
listener.on${eventname}(args);
}
}
public interface ${eventname}Listener extends EventListener
{
public void on${eventname}(${eventname}Args args);
}
public class ${eventname}Args extends EventObject
{
public ${eventname}Args(Object source${cursor})
{
super(source);
}
}
If you have events that share a single EventObject, just delete the customized one inserted by the template and change the appropriate parts of raise___() and on____().
I had written a nice, little, elegant eventing mechanism using a generic interface and generic class, but it wouldn't work due to the way Java handles generics. =(
Edit:
1) I ran into the issue where threads were adding/removing listeners while an event was taking place. The List can't be modified while in use, so I added synchronized blocks where the list of listeners is being accessed or used, locking on the list itself.
Insert test methods should-given-when-then
I saw a similar version to this one recently while pair programming with a very good developer and friend, and I think it could be a nice addition to this list.
This template will create a new test method on a class, following the Given - When - Then approach from the behavior-driven development (BDD) paradigm on the comments, as a guide for structuring the code. It will start the method name with "should" and let you replace the rest of the dummy method name "CheckThisAndThat" with the best possible description of the test method responsibility. After filling the name, TAB will take you straight to the // Given section, so you can start typing your preconditions.
I have it mapped to the three letters "tst", with description "Test methods should-given-when-then" ;)
I hope you find it as useful as I did when I saw it:
#Test
public void should${CheckThisAndThat}() {
Assert.fail("Not yet implemented");
// Given
${cursor}
// When
// Then
}${:import(org.junit.Test, org.junit.Assert)}
Spring Injection
I know this is sort of late to the game, but here is one I use for Spring Injection in a class:
${:import(org.springframework.beans.factory.annotation.Autowired)}
private ${class_to_inject} ${var_name};
#Autowired
public void set${class_to_inject}(${class_to_inject} ${var_name}) {
this.${var_name} = ${var_name};
}
public ${class_to_inject} get${class_to_inject}() {
return this.${var_name};
}
Here is a constructor for non-instantiable classes:
// Suppress default constructor for noninstantiability
#SuppressWarnings("unused")
private ${enclosing_type}() {
throw new AssertionError();
}
This one is for custom exceptions:
/**
* ${cursor}TODO Auto-generated Exception
*/
public class ${Name}Exception extends Exception {
/**
* TODO Auto-generated Default Serial Version UID
*/
private static final long serialVersionUID = 1L;
/**
* #see Exception#Exception()
*/
public ${Name}Exception() {
super();
}
/**
* #see Exception#Exception(String)
*/
public ${Name}Exception(String message) {
super(message);
}
/**
* #see Exception#Exception(Throwable)
*/
public ${Name}Exception(Throwable cause) {
super(cause);
}
/**
* #see Exception#Exception(String, Throwable)
*/
public ${Name}Exception(String message, Throwable cause) {
super(message, cause);
}
}
I like a generated class comment like this:
/**
* I...
*
* $Id$
*/
The "I..." immediately encourages the developer to describe what the class does. I does seem to improve the problem of undocumented classes.
And of course the $Id$ is a useful CVS keyword.
I've had a lot of use of these snippets, looking for null values and empty strings.
I use the "argument test"-templates as the first code in my methods to check received arguments.
testNullArgument
if (${varName} == null) {
throw new NullPointerException(
"Illegal argument. The argument cannot be null: ${varName}");
}
You may want to change the exception message to fit your company's or project's standard. However, I do recommend having some message that includes the name of the offending argument. Otherwise the caller of your method will have to look in the code to understand what went wrong. (A NullPointerException with no message produces an exception with the fairly nonsensical message "null").
testNullOrEmptyStringArgument
if (${varName} == null) {
throw new NullPointerException(
"Illegal argument. The argument cannot be null: ${varName}");
}
${varName} = ${varName}.trim();
if (${varName}.isEmpty()) {
throw new IllegalArgumentException(
"Illegal argument. The argument cannot be an empty string: ${varName}");
}
You can also reuse the null checking template from above and implement this snippet to only check for empty strings. You would then use those two templates to produce the above code.
The above template, however, has the problem that if the in argument is final you will have to amend the produced code some (the ${varName} = ${varName}.trim() will fail).
If you use a lot of final arguments and want to check for empty strings but doesn't have to trim them as part of your code, you could go with this instead:
if (${varName} == null) {
throw new NullPointerException(
"Illegal argument. The argument cannot be null: ${varName}");
}
if (${varName}.trim().isEmpty()) {
throw new IllegalArgumentException(
"Illegal argument. The argument cannot be an empty string: ${varName}");
}
testNullFieldState
I also created some snippets for checking variables that is not sent as arguments (the big difference is the exception type, now being an IllegalStateException instead).
if (${varName} == null) {
throw new IllegalStateException(
"Illegal state. The variable or class field cannot be null: ${varName}");
}
testNullOrEmptyStringFieldState
if (${varName} == null) {
throw new IllegalStateException(
"Illegal state. The variable or class field cannot be null: ${varName}");
}
${varName} = ${varName}.trim();
if (${varName}.isEmpty()) {
throw new IllegalStateException(
"Illegal state. The variable or class field " +
"cannot be an empty string: ${varName}");
}
testArgument
This is a general template for testing a variable. It took me a few years to really learn to appreciate this one, now I use it a lot (in combination with the above templates of course!)
if (!(${varName} ${testExpression})) {
throw new IllegalArgumentException(
"Illegal argument. The argument ${varName} (" + ${varName} + ") " +
"did not pass the test: ${varName} ${testExpression}");
}
You enter a variable name or a condition that returns a value, followed by an operand ("==", "<", ">" etc) and another value or variable and if the test fails the resulting code will throw an IllegalArgumentException.
The reason for the slightly complicated if clause, with the whole expression wrapped in a "!()" is to make it possible to reuse the test condition in the exception message.
Perhaps it will confuse a colleague, but only if they have to look at the code, which they might not have to if you throw these kind of exceptions...
Here's an example with arrays:
public void copy(String[] from, String[] to) {
if (!(from.length == to.length)) {
throw new IllegalArgumentException(
"Illegal argument. The argument from.length (" +
from.length + ") " +
"did not pass the test: from.length == to.length");
}
}
You get this result by calling up the template, typing "from.length" [TAB] "== to.length".
The result is way funnier than an "ArrayIndexOutOfBoundsException" or similar and may actually give your users a chance to figure out the problem.
Enjoy!
I use this for MessageFormat (using Java 1.4). That way I am sure that I have no concatenations that are hard to extract when doing internationalization
i18n
String msg = "${message}";
Object[] params = {${params}};
MessageFormat.format(msg, params);
Also for logging:
log
if(logger.isDebugEnabled()){
String msg = "${message}"; //NLS-1
Object[] params = {${params}};
logger.debug(MessageFormat.format(msg, params));
}
My favorite few are...
1: Javadoc, to insert doc about the method being a Spring object injection method.
Method to set the <code>I${enclosing_type}</code> implementation that this class will use.
*
* #param ${enclosing_method_arguments}<code>I${enclosing_type}</code> instance
2: Debug window, to create a FileOutputStream and write the buffer's content's to a file.
Used for when you want to compare a buffer with a past run (using BeyondCompare), or if you can't view the contents of a buffer (via inspect) because its too large...
java.io.FileOutputStream fos = new java.io.FileOutputStream( new java.io.File("c:\\x.x"));
fos.write(buffer.toString().getBytes());
fos.flush();
fos.close();