Detect file changes in Spring Integration - java

Use case: I want to listen to a file directory, and every time someone makes a change on the file, I want it to start a process.
This is my configuration so far:
<int-file:inbound-channel-adapter directory="${dir}" auto-startup="${auto.startup}" prevent-duplicates="true" filter="inputfilefilter" channel=rulesChannel">
<int:poller fixed-delay="${delay}" />
</int-file:inbound-channel-adapter>
where inputFileFilteris a custom bean and rulesChannel is the processing later.
The inputFileFilter takes an array of files and returns a list of files, sorted on file ending. This seems to be pulling endlessly, and the "prevent-duplicates"-check is done after the filter (i.e. the file is added, but it seems like it's not sent to the rulesChannel).
Anyway, my problem is that I need this whole thing to pick up file changes, not new files. Mainly, it's a configuration file that is being changed every now and then, and I need to update it to keep it in sync.
Yes, this is a horrible solution all over, but it's not really my call, and it seems I have no choice.
Any good ideas?
edit: I've played a bit around with http://docs.spring.io/spring-integration/reference/html/files.html#_watchservicedirectoryscanner to see if I could perhaps copy the class and use it with StandardWatchEventKinds.ENTRY_MODIFY but it doesnt seem to help.
Basically, If I had a good way to just "start a thread and keep it running", I would be fine as well.

What I had to do was implement my own DefaultDirectoryScanner.
It registers a watcher at startup, and checks the watcher when it receives a request from the inbound-channel-adapter through listEligibleItems(..)
To be able to handle two separate file directories, I simply added two different watchers and two different file pollers. This is mainly to ensure readability in the code and to avoid hacking my way around the "directory"-part of the inbound-channel-adapter.

Related

Oracle-UCM service CHECKIN_UNIVERSAL is throwing errors when trying to checkin an existing file

I'm working on Java code that checks whether a file exists in the system and whether it's checked out. After these checks it calls the CHECKIN_UNIVERSAL service. This is where it stops. Checking in a new file works just fine, but it's the checking in of an existing file that's giving errors.
The specific error displayed (without making modifications to my original code) is !cscheckinitemexists. A bunch of googling turned up the solution to clear the data binder, yet then it comes up with the error that it cannot retrieve or use the security token.
Here's the code I use to clear and retrieve the data binder:
m_binder.clearResultSets();
m_binder.getLocalData().clear();
m_binder.setEnvironment(new IdcProperties(SharedObjects.getSecureEnvironment()));
What does the rest of your code look like? You can link to a Gist.
Generally, I have run into this due to data pollution (as you stated).
Is there a reason you are using m_binder instead of creating a brand new DataBinder?
After looking at your gist, you are using m_binder (the DataBinder from the service) to execute CHECKIN_UNIVERSAL. Don't do this. Use a separate DataBinder (as you did for the DOC_INFO_BY_NAME service call).
Either use requestBinder or a new DataBinder.
Another way to avoid this issue is to simply not look for the checkout. CHECKIN_UNIVERSAL supports a flag that checks out a content item if it's not already checked out.
Add the flag "isForceCheckout" to your binder, with a value of "1".

Java saving strings

I have a RuneScape Private Server project coded in Java, and am trying to code a personal "tag" that players can use. I have managed to do this, but everytime there is a restart on the server, their "tag" gets reset to "null".
Their "tag" is initalized by doing a command ";;settag [name]". Their tag is then set to whatever they want. I have done this through a string:
if (command[0].equals("settag")) {
newTag = getCompleteString(command, 1);
newTag = player.yellTag
player.sendMessage("Your tag is now:" +newTag);
}
I am unsure what the most efficient way to fix this would be, I am thinking of just loading and saving through .xml/.txt files. By the way, player.yellTag is where the next command (::mytag) searches it from, which works fine, until there is a restart of the server.
it all depends on the context of your application. If you are planning on having less than a few hundreds players, then a xml file may be ok. You should look at JAXB, which is, afaict, the standard way to store your objects in Java. You can also store them as JSON files, using gson which is way simpler to use and implement than XML stuff.
But if you get to have more than thousands of players, you may want to get some more efficient way to serialize your tags by putting them in a database, and thus an ORM library like hibernate could help you do that.
You may want to make your own stuff, like a tag directory full of files named after unique ids of your players containing the players' tag... It's a lot more "hackish" but still quite efficient.

How to avoid hardcoding file-references?

My Code:
I'm currently developing a game and throughout several different parts of the code I'm using some resources (Images/Sounds/Animations etc.). To avoid loading the same resource twice I wrote a ResourceManager, that returns the wanted resource if I pass a string to it.
Here's an example:
Image myImage = imageManager.getImage("princess");
This way I can reference a resource without knowing the name of the file or position of it, when I want to use it.
The trick here is that I have to load the images before I can get them like so:
imageManager.loadImage("res/princessImage.png", "princess");
This creates the ImageObject from the given file, and stores it into a HashMap with the given key.
My Problem:
I really don't want to hardcode the paths to these resources, because I'd have to change the sourcecode every time I decide to move or rename any of the resource-files.
A possible solution (?):
I thought about creating another HashMap that reads some kind of configFile and maps the in-code-resource-names to the resource-paths in a HashMap. The file would look somewhat like this:
princess: res/princess.png
hero: res/hero.png
sword: res/items/sword.png
This way I could use resource-names like "princess", "hero" or "sword" safely and don't worry about their position on the hard drive while I'm coding. Whenever I move or rename a resource-file I just update the path/name in this configFile and everything would be fine.
On the other hand I think it's pretty ugly to have one giant file that maps every in-code-resource-name to a path. This could result in one giant String to String HashMap which I'd have to store in the ResourceManager aswell. Things could get pretty confusing/unclear.
Does anyone have a better solution for me?
I'd really appreciate your help,
Thanks :)
Using a config or resource file as you described is a fine approach. Instead of populating a HashMap, though, consider using ResourceBundle or PropertyResourceBundle. It is designed to hold/access such things. http://docs.oracle.com/javase/6/docs/api/java/util/ResourceBundle.html

Need help using java threads to download file parts

I am trying to download a file from a server in a user specified number of parts (n). So there is a file of x bytes divided into n parts with each part downloading a piece of the whole file at the same time. I am using threads to implement this, but I have not worked with http before and do not really understand how downloading a file really works. I have read up on it and it seems "Range" needs to be used, but I do not know how to download different parts and being able to append them without corrupting the data.
(Since it's a homework assignment I will only give you a hint)
Appending to a single file will not help you at all, since this will mess up the data. You have two alternatives:
Download from each thread to a separate temporary file and then merge the temporary files in the right order to create the final file. This is probably easier to conceive, but a rather ugly and inefficient approach.
Do not stick to the usual stream-style semantics - use random access (1, 2) to write data from each thread straight to the right location within the output file.

Using A BlockingQueue With A Servlet To Persist Objects

First, this may be a stupid question, but I'm hoping someone will tell me so, and why. I also apologize if my explanation of what/why is lacking.
I am using a servlet to upload a HUGE (247MB) file, which is pipe (|) delineated. I grab about 5 of 20 fields, create an object, then add it to a list. Once this is done, I pass the the list to an OpenJPA transactional method called persistList().
This would be okay, except for the size of the file. It's taking forever, so I'm looking for a way to improve it. An idea I had was to use a BlockingQueue in conjunction with the persist/persistList method in a new thread. Unfortunately, my skills in java concurrency are a bit weak.
Does what I want to do make sense? If so, has anyone done anything like it before?
Servlets should respond to requests within a short amount of time. In this case, the persist of the file contents needs to be an asynchronous job, so:
The servlet should respond with some text about the upload job, expected time to complete or something like that.
The uploaded content should be written to some temp space in binary form, rather than keeping it all in memory. This is the usual way the multi-part post libraries to their work.
You should have a separate service that blocks on a queue of pending jobs. Once it gets a job, it processes it.
The 'job' is simply some handle to the temporary file that was written when the upload happened... and any metadata like who uploaded it, job id, etc.
The persisting service needs to upload a large number of rows, but make it appear 'atomic', either model the intermediate state as part of the table model(s), or write to temp spaces.
If you are writing to temp tables, and then copying all the content to the live table, remember to have enough log space and temp space at the database level.
If you have a full J2EE stack, consider modelling the job queue as a JMS queue, so recovery makes sense. Once again, remember to have proper XA boundaries, so all the row persists fall within an outer transaction.
Finally, consider also having a status check API and/or UI, where you can determine the state of any particular upload job: Pending/Processing/Completed.

Categories

Resources