Expected: When i run application in debug mode and pulling the endpoint, bytes still appear to be null however i did implement ApplicationEvent and passed ApplicationStartedEvent, then I have override onApplicationEvent and called my method there, which should lead to code execution once application started and bytes should already have a value. Have I missed something
public class FaqAttachment implements ApplicationListener<ApplicationStartedEvent> {
private final String fileName = "FAQ.pdf";
private byte[] bytes;
public Attachment asAttachment() {
return new Attachment(pdfToBytes(), fileName);
}
private byte[] pdfToBytes() {
if (bytes == null) {
try (FileInputStream inputStream = new FileInputStream(new File(ClassLoader.getSystemResource(fileName).getFile()))) {
this.bytes = ByteStreams.toByteArray(inputStream);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return bytes;
}
#Override
public void onApplicationEvent(ApplicationStartedEvent event) {
pdfToBytes();
}
This should work :
#Component
public class FaqAttachment {
private final String fileName = "FAQ.pdf";
private byte[] bytes;
public Attachment asAttachment() {
return new Attachment(pdfToBytes(), fileName);
}
private byte[] pdfToBytes() {
if (bytes == null) {
try (FileInputStream inputStream = new FileInputStream(new File(ClassLoader.getSystemResource(fileName).getFile()))) {
this.bytes = ByteStreams.toByteArray(inputStream);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return bytes;
}
#EventListener
public void onApplicationStartedEvent(ApplicationStartedEvent event) {
pdfToBytes();
}
}
Related
After running a Junit test for boolean type serialization, it is always failed with true value my serialize method as follows
public static void serializeBoolean(boolean objectToSerialize, OutputStream outputStream) {
byte[] bytesArr = new byte[1];
ByteBuffer.wrap(bytesArr).put((byte) (objectToSerialize ? 1 : 0));
try {
outputStream.write(bytesArr);
} catch (IOException e) {
e.printStackTrace();
}
}
And my deserialize method as follows
public static boolean deserializeBoolean(InputStream inputStream) {
byte[] databytesArr = new byte[1];
if (ByteBuffer.wrap(databytesArr).get() == 1) {
return true;
}
else {
return false;
}
}
Finally, I wrote a unit test as follows
public class BooleanSerializerTest {
private InputStream iStream;
private ByteArrayOutputStream oStream;
#Before
public void init() {
oStream = new ByteArrayOutputStream();
}
boolean serialzeAndDeserializeObject(boolean booleanValue) {
OutputStreamUtil.serializeBoolean(booleanValue, oStream);
iStream = new ByteArrayInputStream(oStream.toByteArray());
return InputStreamUtil.deserializeBoolean(iStream);
}
#Test
public void equalToTrue() {
boolean booleanValue = true;
boolean deserializedBooleanValue =
serialzeAndDeserializeObject(booleanValue);
assertThat(deserializedBooleanValue).isEqualTo(booleanValue);
}
#Test
public void equalToFalse() {
boolean booleanValue = false;
boolean deserializedBooleanValue =
serialzeAndDeserializeObject(booleanValue);
assertThat(deserializedBooleanValue).isEqualTo(booleanValue);
}
}
equalToFalse() test was succeed but equalToTrue() is always fail
what was wrong? and how to fix it?
you should add inputStream.read(databytesArr); in the method deserializeBoolean as follow:
public static boolean deserializeBoolean(InputStream inputStream) {
byte[] databytesArr = new byte[1];
try {
inputStream.read(databytesArr);
} catch (IOException e) {
e.printStackTrace();
}
if (ByteBuffer.wrap(databytesArr).get() == 1) {
return true;
} else {
return false;
}
}
Since the input parameter inputStream isn't used you get always the same result update the deserializeBoolean method as follows:
public static boolean deserializeBoolean(InputStream inputStream) throws IOException {
byte[] databytesArr = new byte[1];
inputStream.read(databytesArr);
return ByteBuffer.wrap(databytesArr).get() == 1;
}
Thereafter the tests will succeed.
I have written a Netty.io system in which I can easily send text files back and forth, but now I do not only want to send text files at the byte level, but if I announce before that comes a jar, even send a jar file at byte level.
Now I have tried only to send them like a normal file where logically a corrupt jar comes out.
So I send the text files:
public void sendFile(Channel channel, File files, String path) {
new Thread(new Runnable() {
#Override
public void run() {
sendFileInfo(channel,files,path);
while (file.containsKey(files.getName())) {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
FileInputStream fis = new FileInputStream(files);
byte[] bytes = new byte[512];
int i =0;
int length;
while((length =fis.read(bytes))>0){
PacketOutFile512Bytes bit = new PacketOutFile512Bytes(i,files.getName(),length,bytes);
channel.writeAndFlush(bit);
if(!cache.containsKey(files.getName()))
cache.put(files.getName(),new HashMap<>());
HashMap<Integer, Timer> timecache = cache.get(files.getName());
timecache.put(i,new Timer());
timecache.get(i++).schedule(new TimerTask() {
#Override
public void run() {
channel.writeAndFlush(bit);
}
},Main.getInstance().getTimeout()*1000,Main.getInstance().getTimeout()*1000);
Thread.sleep(100);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
public void writeFile(Channel channel, String file, int length){
new Thread(new Runnable() {
#Override
public void run() {
File sending = new File(path.get(file),file);
try {
sending.createNewFile();
FileOutputStream fos = new FileOutputStream(file);
for(int i =0; i< amountofPackets.get(file);i++)
fos.write(cache.get(file).get(i),0,length);
fos.close();
channel.writeAndFlush(new PacketOutFileSucess(file));
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
Now I am looking for a method how to copy a jar on level of bytes that I can send with the same package.
This is how the packet looks for the byte snippet:
import de.letsplaybar.fileserver.ValueSizeException;
import lombok.Getter;
public class PacketInFile512Bytes implements Packet {
private #Getter int packetId;
private #Getter String name;
private #Getter int length;
private #Getter byte[] value;
public PacketInFile512Bytes() {
value = new byte[512];
}
public PacketInFile512Bytes(int packetId, String name, int length, byte[] value) throws ValueSizeException {
if(value.length != 512)
throw new ValueSizeException();
this.packetId = packetId;
this.name = name;
this.length = length;
this.value = value;
}
#Override
public void read(PacketSerilizer serilizer) {
packetId = serilizer.readInt();
name = serilizer.readString();
length = serilizer.readInt();
for (int i = 0; i<512;i++)
value[i] = serilizer.readByte();
}
#Override
public void write(PacketSerilizer serilizer) {
serilizer.writeInt(packetId);
serilizer.writeString(name);
serilizer.writeInt(length);
serilizer.writeBytes(value);
}
}
Who knows a way how I can do that?
Ever thank you in advance.
Letsplaybar
My app is saving a hashmap before it stops and when it starts again loads the same hashmap so changes could be made to it. I am using Serialization.
Storage class:
public class Storage {
private Map<String, String> storage;
private String projectStorageFilePath;
public Storage() {
this.storage = new ConcurrentHashMap<String, String>();
makeDir();
}
/**
* If the file in which the map objects will be saved doesn't exist in the
* user home directory it creates it.
*/
private void makeDir() {
File projectHomeDir = new File(System.getProperty("user.home"), ".TestMap");
String projectHomeDirPath = projectHomeDir.getAbsolutePath();
File projectStorageFile = new File(projectHomeDirPath, "storage.save");
projectStorageFilePath = projectStorageFile.getAbsolutePath();
if (!projectHomeDir.exists()) {
projectHomeDir.mkdir();
try {
projectStorageFile.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
}
#SuppressWarnings("unchecked")
public boolean load() {
boolean isLoaded = false;
ObjectInputStream ois = null;
try {
File file = new File(projectStorageFilePath);
if (file.length() != 0) {
//loading the map
ois = new ObjectInputStream(new FileInputStream(file));
storage = (ConcurrentHashMap<String, String>) ois.readObject();
isLoaded = true;
}
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
} finally {
try {
if (null != ois) {
ois.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return isLoaded;
}
public boolean save() {
boolean isSaved = false;
ObjectOutputStream oos = null;
try {
//saving
oos = new ObjectOutputStream(new FileOutputStream(projectStorageFilePath));
oos.writeObject(storage);
isSaved = true;
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (null != oos) {
oos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return isSaved;
}
public Map<String, String> getStorage() {
return this.storage;
}
}
The class in which I am trying to do something with that hashmap:
public class DoSomethingWithMap {
private Map<String, String> storage;
public DoSomethingWithMap(Map<String, String> storage) {
this.storage = storage;
}
public void addToMap(String key, String value) {
this.storage.put(key, value);
}
public void printMap() {
System.out.println(this.storage);
}
}
When I run it the first time it works fine:
public class Main {
public static void main(String[] args) {
Storage s = new Storage();
DoSomethingWithMap something = new DoSomethingWithMap(s.getStorage());
if (s.load()) {
System.out.println(s.getStorage());
}
something.addToMap("2", "test2");
something.addToMap("4", "test4");
something.addToMap("5", "test5");
if (s.save()) {
System.out.println(s.getStorage());
}
}
}
Output:
{} //empty map which is ok because it has never been saved before
{3=test3, 4=test4, 5=test5} //changes during runtime are saved
The problem is when I start Main again and try to make changes to the saved map:
public static void main(String[] args) {
Storage s = new Storage();
DoSomethingWithMap something = new DoSomethingWithMap(s.getStorage());
if (s.load()) {
System.out.println(s.getStorage());
}
something.printMap();
something.addToMap("6", "newTest");
something.addToMap("7", "newTest");
something.addToMap("8", "newTest");
something.printMap();
if (s.save()) {
System.out.println(s.getStorage());
}
}
Output:
{3=test3, 4=test4, 5=test5} //loading the map works fine
{} //here it should be same as previous line but is not
{6=newTest, 7=newTest, 8=newTest} //DoSomethingWithMap.printMap is printing only the changes during runtime
{3=test3, 4=test4, 5=test5} // changes during runtime are not saved
It is obvious DoSomethingWithMap class is not using the map which was given to it. Why? Which map is using? How I can fix that?
Thank you.
You are creating a new instance of the Map in your load method:
storage = (ConcurrentHashMap<String, String>) ois.readObject();
To fix you can clear the current map and then add all the values from the loaded one:
//loading the map
ois = new ObjectInputStream(new FileInputStream(file));
storage.clear();
storage.putAll((ConcurrentHashMap<String, String>) ois.readObject());
To prevent such error in the future, you could make those fields final and thus you will get error reports.
Is there an example of a very barebones Netty handler which simply gets whatever data is sent on the wire and writes it to a file?
I was thinking of something along the lines of this:
public class SimpleHandler extends SimpleChannelUpstreamHandler {
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
HttpRequest request = (HttpRequest) e.getMessage();
// get data from request and write to a file
}
Any ideas? Thanks for any thoughts
You could also just use this method to transfer the content of the ChannelBuffer to an OutputStream:
http://netty.io/docs/stable/api/org/jboss/netty/buffer/ChannelBuffer.html#readBytes(java.io.OutputStream,%20int)
So something like this:
public class FileWriterHandler extends SimpleChannelHandler {
private final String filename;
public FileWriterHandler(String filename) {
this.filename = filename;
}
#Override
public void messageReceived(ChannelHandlerContext context, MessageEvent event) throws Exception{
ChannelBuffer buffer = (ChannelBuffer)event.getMessage();
FileOutputStream out = null;
try {
out = new FileOutputStream(filename, true)
buffer.readBytes(out, buffer.readableBytes());
} finally {
if (out != null) out.close();
}
}
}
I wrote one of these for testing a while back:
public class FileWriterHandler extends SimpleChannelHandler {
private final String filename;
public FileWriterHandler(String filename) {
this.filename = filename;
}
#Override
public void messageReceived(ChannelHandlerContext context, MessageEvent event) {
ChannelBuffer buffer = (ChannelBuffer)event.getMessage();
byte[] bytes = new byte[buffer.readableBytes()];
buffer.readBytes(bytes);
try {
DataOutputStream stream = new DataOutputStream(new FileOutputStream(filename, true));
stream.write(bytes, 0, bytes.length);
stream.flush();
stream.close();
} catch (IOException ex) {
throw runtime(ex);
}
}
}
This is just for test hence i'm just re-throwing exceptions and not really dealing with them properly. Hope that's helpful.
You would set this up as follows:
ServerBootstrap bootstrap = initializedSomehow();
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
#Override
public ChannelPipeline getPipeline() {
return pipeline(new FileWriterHandler("yourfile.txt"));
}
});
When Im trying to read an object and store in arraylist but im getting an exception this is the part of code where im facing a problem.
public class Customer implements Serializable {
private String username;
private String password;
private int age;
private String accttype;
private String acctno;
private float amount;
Customer() {
System.out.println("Im in Customer");
}
public boolean writeToDataBase(String uname, String pwd, int cage, String caccttype, String cacctno, float camount) throws IOException {
Customer custobj = new Customer();
FileOutputStream fos=null;
ObjectOutputStream oos=null;
custobj.username = uname;
custobj.password = pwd;
custobj.age = cage;
custobj.accttype = caccttype;
custobj.acctno = cacctno;
custobj.amount = camount;
try {
fos=new FileOutputStream("Customerdetails.txt",true);
oos=new ObjectOutputStream(fos);
oos.writeObject(custobj);
oos.close();
fos.close();
return true;
} catch (Exception ex) {
ex.printStackTrace();
return false;
}
finally
{
fos.close();
oos.close();
}
}
public boolean retriveFromDataBase(int a) throws IOException
{
try {
Customer custobj = new Customer();
FileInputStream fis=null;
ObjectInputStream ois=null;
ArrayList<Customer> custlist;
try {
custlist = new ArrayList<Customer>();
fis = new FileInputStream("Customerdetails.txt");
ois = new ObjectInputStream(fis);
while (fis.available()!=0) {
custobj=(Customer)ois.readObject();
custlist.add(custobj);
}
System.out.println("Customer List" + custlist.size());
if (a == 3) {
for (int i = 0; i < custlist.size(); i++) {
custobj = custlist.get(i);
custobj.displayCustomers();
}
}
return true;
} catch (Exception ex) {
System.out.println(ex.toString());
System.out.println("No users are presnt in the file");
return false;
}
finally
{
ois.close();
fis.close();
}
}
catch(Exception ex)
{
System.out.println(ex.toString());
return false;
}
}
public void displayCustomers()
{
try
{
System.out.println("details"+username+"\t"+age+"\t"+password+"\t"+acctno+"\t"+accttype+"\t"+amount);
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
}
Does your object implement the Serializiable or Externalizeable interface? If yes do you use non transitive objects that don't implement serializiable/externalizeable and don't offer a argumentless default constructor?
Without further information (which exception, more code) it's hard to say.
I noted that the program throws java.io.StreamCorruptedException, when you run it for the second time. It works fine when you run it only once.
The problem is that you cannot APPEND to the same file : Customerdetails.txt every time you serialize in writeToDatabase(..) method. So remove the append flag : "true" in the call to constructor of FileOutputStream in writeToDatabase(..) method.