How to bind messages in javafx without using eclipse.osgi NLS? - java

I have a messages.properties file that contains all string messages used in my application.
I would like to bind these messages to a java class fields and use directly in other classes.
Can this be achieved without using NLS? By some approach in javafx? Because I do not want to add eclipse dependency in UI classes.

Java provides property file reading capability right from the box. You can do adjustment to suit your actual use-case.
For example:
public final class Messages {
private Messages() {
loadFile();
}
private static final class ThreadSafeSingleton {
private static final Messages INSTANCE = new Messages();
}
public static Messages getInstance() {
return ThreadSafeSingleton.INSTANCE;
}
private final Properties props = new Properties();
private void loadFile() {
InputStream is = null;
try {
is = new FileInputStream("messages.properties");
props.load(is);
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public String getMessage(String key) {
if (key == null && key.isEmpty()) return "";
return props.getProperty(key);
}
}
Edit
In order to use these values as if it is a constant, you need to pretty much make everything static:
public final class Messages {
private Messages() {} // Not instantiable
private static final Properties props = loadFile(); // Make sure this static field is at the top
public static final String FOO = getMessage("foo");
public static final String BAR = getMessage("bar");
private static Properties loadFile() {
final Properties p = new Properties();
InputStream is = null;
try {
is = new FileInputStream("messages.properties");
p.load(is);
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return p;
}
public static String getMessage(String key) {
if (key == null && key.isEmpty()) return "";
return props.getProperty(key);
}
}
Be warned again, the Properties field must always be the top-most field declared in the class, because the class loader will load the fields top-down for all static fields whose value is computed at runtime (i.e. set by a static method).
Another point, this example does not handles what happens if the file is not file - it simply returns a Properties that has no value.

Related

Serialization of String[]: how to convert String value to String[] one?

here is code for main
public static void main(String[] args) {
Container container= new Container();
Serializator serializator = new Serializator();
container.setvalue("1st val");
serializator.serialization(container);
}
here is code for container
public class Container implements Serializable {
private static final long serialVersionUID = 1L;
/**
* Holds the elements of a container.
*/
private String[] values;
public String[] getvalue() {
return values;
}
public void setvalue(String[] values) {
this.values=values;
}
}
here is code for a serializator
public class Serializator {
public boolean serialization(Container container) {
boolean flag=false;
File file= new File("C:/conatiner.data");
ObjectOutputStream oos = null;
try {
FileOutputStream fos= new FileOutputStream(file);
if(fos != null) {
oos= new ObjectOutputStream(fos);
oos.writeObject(container);
flag=true;
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if(oos != null) {
try {
oos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return flag;
}
}
Well, the program should be working in a following way: you create a container that has an array of strings,(you can set the values in it) and then the program must serialize it. but the problem is that the tutorial worked with the String value, but not the String[] one. how can i make it understand the String[] value and insert it?
The crashlog is the following
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
The method setvalue(String[]) in the type Container is not applicable for the arguments (String)
at ua.khpi.oop.taradai06.program6.main(program6.java:7)
"container.setvalue("1st val");"
First, let's focus on the bug:
In the container, you promised you will send an array of string in the function setValue, but you are sending a single string.
There are two things you could do;
keep the container code as it is and send array of strings from main
Change the container code and let setValue get a single string value and add it to the values array
And you main question related with serialisation please check that post
In order to accept both String and String[] as an input parameter to Container::setvalue method, the varargs should be used, then a single String is accepted as an array consisting of one element.
Also, Java naming conventions for getters/setters of Java Beans specify to capitalize the property names after get/set verb: Getter and setter method names are composed of the word get or set, respectively, plus the property name with the first character of each word capitalized, so the methods should be names as getValues/setValues:
// Container class
public void setValues(String... values) {
this.values = values;
}
Then this method can be invoked as follows without additional overloading:
container.setValues(); // empty array new String[0]
container.setValues("a string"); // new String[1]{"a string"}
container.setValues("a", "b"); // new String[2]{"a", "b"}
container.setValues(new String[]{"1", "2", "3"}); // common array
If you promised you'll use the String[] parameter, then you should note that.
The following version of using setvalue does this work perfectly
container.setvalue(new String[] {"1st val","2nd val","3rd val"});
OK I hope I helped you look in the class "Container" in "setvalue" function, you gived it the parameter "1st value"(Its one string) but it needs a String array. So you can replace your code with this:
main class:
public class main {
public static void main(String[] args) {
Container container= new Container();
Serializator serializator = new Serializator();
container.setvalue("1st value", 0);
serializator.serialization(container);
}
}
Container class:
import java.io.Serializable;
public class Container implements Serializable {
private static final long serialVersionUID = 1L;
/**
* Holds the elements of a container.
*/
int AnyNumberYouWant = 100;
private String[] values = new String[AnyNumberYouWant];
public String[] getvalue() {
return values;
}
public void setvalue(String value, int index) {
this.values[index]=value;
}
}
Serializator class
import java.io.*;
public class Serializator {
public boolean serialization(Container container) {
boolean flag=false;
File file= new File("C:/Container/container.data");
ObjectOutputStream oos = null;
try {
FileOutputStream fos= new FileOutputStream(file);
if(fos != null) {
oos= new ObjectOutputStream(fos);
oos.writeObject(container);
flag=true;
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if(oos != null) {
try {
oos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return flag;
}
}
And I solved another errors that was there in the code. So I tried it and worked correctly. I hope that I helped you.

How do I connect the java sdk to qldb?

I try this tutorial
https://docs.aws.amazon.com/qldb/latest/developerguide/getting-started.java.step-2.html but I don't understand how to connect to qldb with the java sdk.
I only need to update a document, but this documentation is so complex. Does anyone have any idea? Or something for dummies.
public final class ConnectToLedger {
public static final Logger log = LoggerFactory.getLogger(ConnectToLedger.class);
public static AWSCredentialsProvider credentialsProvider;
public static String endpoint = null;
public static String ledgerName = Constants.LEDGER_NAME;
public static String region = null;
public static PooledQldbDriver driver = createQldbDriver();
private ConnectToLedger() { }
/**
* Create a pooled driver for creating sessions.
*
* #return The pooled driver for creating sessions.
*/
public static PooledQldbDriver createQldbDriver() {
AmazonQLDBSessionClientBuilder builder = AmazonQLDBSessionClientBuilder.standard();
if (null != endpoint && null != region) {
builder.setEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration(endpoint, region));
}
if (null != credentialsProvider) {
builder.setCredentials(credentialsProvider);
}
return PooledQldbDriver.builder()
.withLedger(ledgerName)
.withRetryLimit(Constants.RETRY_LIMIT)
.withSessionClientBuilder(builder)
.build();
}
/**
* Connect to a ledger through a {#link QldbDriver}.
*
* #return {#link QldbSession}.
*/
public static QldbSession createQldbSession() {
return driver.getSession();
}
public static void main(final String... args) {
try (QldbSession qldbSession = createQldbSession()) {
log.info("Listing table names ");
for (String tableName : qldbSession.getTableNames()) {
log.info(tableName);
}
} catch (QldbClientException e) {
log.error("Unable to create session.", e);
}
}
}
I'm sorry the documentation is complex. Here is a minimal version of the code you referred to with all the customization and options stripped out. It assumes your environment is setup to use the correct AWS region and credentials.
PooledQldbDriver driver = PooledQldbDriver.builder()
.withLedger("my-ledger-name")
.withSessionClientBuilder(AmazonQLDBSessionClientBuilder.standard())
.build();
try (QldbSession session = driver.getSession()) {
session.execute("UPDATE my-table SET my-field = ?", < Ion value here >);
}
I'd love to help you further, but your question as it stands doesn't make it clear where you got stuck. For example, did you try run the above code and, if so, did you get an error? If you update your question with more information or respond to my answer in the comments I"ll check back in.
so i reduce the code because the example need more experience on QLDB sdk java, and java.
public QldbSession getQldbSession(String ledgerName) {
final AmazonQLDBSessionClientBuilder builder = AmazonQLDBSessionClientBuilder.standard();
if (null != endpoint && null != region) {
builder.setEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration(endpoint, region));
}
if (null != credentialsProvider) {
builder.setCredentials(credentialsProvider);
}
final PooledQldbDriver driver = PooledQldbDriver.builder().withLedger(ledgerName).withRetryLimit(4)
.withSessionClientBuilder(builder).build();
return driver.getSession();
}
Result result = null;
try {
final String query = "!query hereĀ”";
final IonObjectMapper MAPPER = new IonValueMapper(IonSystemBuilder.standard().build());
final List<IonValue> parameters = new ArrayList<>();
parameters.add(MAPPER.writeValueAsIonValue("parameter"));
parameters.add(MAPPER.writeValueAsIonValue("parameter"));
parameters.add(MAPPER.writeValueAsIonValue("parameter"));
result = qldbSession.execute(query, parameters);
} catch (final QldbClientException e) {
System.out.println("Unable to create session.");
} catch (final IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return result;
}

JSP - Running a program with main method and nested static class

I'm a novice when it comes to JSPs and JAVA.
How do I get the output from the below code to display on a jsp, considering that it runs everything from the main and contains non-public methods, a nested static class etc?
I know that we are not supposed to use java code on jsp but my first step in this proof on concept exercise is to get the code running and returning data from a backend then I can set about using EL etc.
I can run the program, with the correct config settings, from within Eclipse and all works fine with the output appearing on the console but I'm really not sure how to access it from within a jsp.
How do I access the static class and static methods from a jsp if they aren't public?
All help greatly appreciated.
public class CustomDestinationDataProvider
{
static class MyDestinationDataProvider implements DestinationDataProvider
{
private DestinationDataEventListener eL;
private HashMap<String, Properties> secureDBStorage = new HashMap<String, Properties>();
public Properties getDestinationProperties(String destinationName)
{
try
{
//read the destination from DB
Properties p = secureDBStorage.get(destinationName);
if(p!=null)
{
//check if all is correct, for example
if(p.isEmpty())
throw new DataProviderException(DataProviderException.Reason.INVALID_CONFIGURATION, "destination configuration is incorrect", null);
return p;
}
return null;
}
catch(RuntimeException re)
{
throw new DataProviderException(DataProviderException.Reason.INTERNAL_ERROR, re);
}
}
public void setDestinationDataEventListener(DestinationDataEventListener eventListener)
{
this.eL = eventListener;
}
public boolean supportsEvents()
{
return true;
}
//implementation that saves the properties in a very secure way
void changeProperties(String destName, Properties properties)
{
synchronized(secureDBStorage)
{
if(properties==null)
{
if(secureDBStorage.remove(destName)!=null)
eL.deleted(destName);
}
else
{
secureDBStorage.put(destName, properties);
eL.updated(destName); // create or updated
}
}
}
} // end of MyDestinationDataProvider
//business logic
void executeCalls(String destName)
{
JCoDestination dest;
try
{
dest = JCoDestinationManager.getDestination(destName);
dest.ping();
System.out.println("Destination " + destName + " works");
step4WorkWithTable(dest);
}
catch(JCoException e)
{
e.printStackTrace();
System.out.println("Execution on destination " + destName+ " failed");
}
}
static Properties getDestinationPropertiesFromUI()
{
//adapt parameters in order to configure a valid destination
Properties connectProperties = new Properties();
// Add code here to set config settings
return connectProperties;
}
public static void main(String[] args)
{
MyDestinationDataProvider myProvider = new MyDestinationDataProvider();
//register the provider with the JCo environment;
//catch IllegalStateException if an instance is already registered
try
{
com.sap.conn.jco.ext.Environment.registerDestinationDataProvider(myProvider);
}
catch(IllegalStateException providerAlreadyRegisteredException)
{
//somebody else registered its implementation,
//stop the execution
throw new Error(providerAlreadyRegisteredException);
}
String destName = "????";
CustomDestinationDataProvider test = new CustomDestinationDataProvider();
//set properties for the destination and ...
myProvider.changeProperties(destName, getDestinationPropertiesFromUI());
//... work with it
test.executeCalls(destName);
}
public static void step4WorkWithTable(JCoDestination dest) throws JCoException
{
JCoFunction function = dest.getRepository().getFunction("BAPI_COMPANYCODE_GETLIST");
if(function == null)
throw new RuntimeException("BAPI_COMPANYCODE_GETLIST not found in SAP.");
try
{
function.execute(dest);
}
catch(AbapException e)
{
System.out.println(e.toString());
return;
}
JCoStructure returnStructure = function.getExportParameterList().getStructure("RETURN");
if (! (returnStructure.getString("TYPE").equals("")||returnStructure.getString("TYPE").equals("S")) )
{
throw new RuntimeException(returnStructure.getString("MESSAGE"));
}
JCoTable codes = function.getTableParameterList().getTable("COMPANYCODE_LIST");
for (int i = 0; i < codes.getNumRows(); i++)
{
codes.setRow(i);
System.out.println(codes.getString("COMP_CODE") + '\t' + codes.getString("COMP_NAME"));
}
//move the table cursor to first row
codes.firstRow();
for (int i = 0; i < codes.getNumRows(); i++, codes.nextRow())
{
function = dest.getRepository().getFunction("BAPI_COMPANYCODE_GETDETAIL");
if (function == null)
throw new RuntimeException("BAPI_COMPANYCODE_GETDETAIL not found in SAP.");
function.getImportParameterList().setValue("COMPANYCODEID", codes.getString("COMP_CODE"));
//We do not need the addresses, so set the corresponding parameter to inactive.
//Inactive parameters will be either not generated or at least converted.
function.getExportParameterList().setActive("COMPANYCODE_ADDRESS",false);
try
{
function.execute(dest);
}
catch (AbapException e)
{
System.out.println(e.toString());
return;
}
returnStructure = function.getExportParameterList().getStructure("RETURN");
if (! (returnStructure.getString("TYPE").equals("") ||
returnStructure.getString("TYPE").equals("S") ||
returnStructure.getString("TYPE").equals("W")) )
{
throw new RuntimeException(returnStructure.getString("MESSAGE"));
}
JCoStructure detail = function.getExportParameterList().getStructure("COMPANYCODE_DETAIL");
System.out.println(detail.getString("COMP_CODE") + '\t' +
detail.getString("COUNTRY") + '\t' +
detail.getString("CITY"));
}//for
}
}

Testing a method that reads and processes data from a file [duplicate]

This question already has answers here:
Mocking Files in Java - Mock Contents - Mockito
(3 answers)
Closed 6 years ago.
I have the following code:
public class FolderServiceImpl implements FolderService {
private static final Logger L = LoggerFactory.getLogger(FolderServiceImpl.class);
public int getStatus(String folderPath) {
int status = 0;
File folderStatusFile = new File(folderPath, ".folderstatus");
if (folderStatusFile.exists()) {
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader(folderStatusFile));
String line = br.readLine();
status = Integer.parseInt(line);
} catch (Exception e) {
L.error("can't read file " + folderStatusFile.getAbsolutePath(), e);
status = 4;
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
L.warn("could not close reader ", e);
}
}
}
} else {
status = 3;
}
return status;
}
}
I want to test this method without creating actual files for every case. I should be using Java 1.7, JUnit 4, Mockito and/or PowerMockito.
Any ideas on how to do that?
I am talking about mocking either the data source or simply changeing the input for the method.
My test looks something like this:
`#Rule
public TemporaryFolder folder = new TemporaryFolder();
private FolderServiceImpl serviceToTest = new FolderServiceImpl();
private String folderPath;
#Before
public void setUp() {
folderPath = folder.getRoot().getAbsolutePath();
try {
folder.newFile(".folderstatus");
} catch (IOException e) {
e.printStackTrace();
}
}
#Test
public void shouldReturnFolderStatus3WhenFolderStatusIsNotFound() {
// given
deleteFolderStatusFile();
// actual
int status = serviceToTest.getFolderStatus(folderPath);
// expected
assertEquals(3, status);
}
#Test
public void shouldReturnFolderStatus4WhenTheStatusIsUnreadable() {
// given
writeStatusToTestFile("Test");
// actual
int status = serviceToTest.getFolderStatus(folderPath);
// expected
assertEquals(4, status);
}
#Test
public void shouldReturnFolderStatusInTheFile() {
// given
writeStatusToTestFile("1");
// actual
int status = serviceToTest.getFolderStatus(folderPath);
// expected
assertEquals(1, status);
}
private void writeStatusToTestFile(String status) {
Path file = Paths.get(folder.getRoot().getAbsolutePath(), ".folderstatus");
try {
Files.write(file, status.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
private void deleteFolderStatusFile() {
Path file = Paths.get(folder.getRoot().getAbsolutePath(), ".folderstatus");
try {
Files.delete(file);
} catch (IOException e) {
e.printStackTrace();
}
}`
Although the answer of #BenHeid may work I'd suggest to change to different approach.
IMHO when ever I use PowerMock(-ito) it is a surrender to bad design.
Also the PowerMock solution will confuse test coverage tools since it changes the Applications byte code after it has been instrumented for coverage measurement.
So the approach I'd prefer is to stick to Clean Code and OOP rules.
One of them is separation of concerns.
In your case the method creates some infrastructure classes (dependencies) to work with, namely FileReader and BufferedReader.
But the instantiation of (direct) dependencies is not a responsibility of a class containing business logic.
Therefore I'd suggest to refactor that code out into a separate class:
class ReaderFactory {
public BufferedReader createFor(File file) throws FileNotFoundException {
return new BufferedReader(new FileReader(file));
}
}
Your Class would change to this:
class FolderServiceImpl {
private static final Logger L = LoggerFactory.getLogger(FolderServiceImpl.class);
private final ReaderFactory readerFactory;
FolderServiceImpl(ReaderFactory readerFactory) {
this.readerFactory = readerFactory;
}
public int getStatus(String folderPath) {
int status = 0;
File folderStatusFile = new File(folderPath, ".folderstatus");
// try "with resource" takes care of closing the reader
try (BufferedReader br = readerFactory.createFor(folderStatusFile);) {
String line = br.readLine();
status = Integer.parseInt(line);
} catch (IOException e) {
status = 3;
} catch (Exception e) {
L.error("can't read file " + folderStatusFile.getAbsolutePath(), e);
status = 4;
}
return status;
}
}
And your Test would be this:
public class FolderServiceImplTest {
private static final String ANY_FILE_NAME = "";
#Rule
public MockitoRule mockitoRule = MockitoJUnit.rule();
#Rule
public ExpectedException thrown = ExpectedException.none();
#Mock
private ReaderFactory readerFactory;
#InjectMocks
FolderServiceImpl sut;
#Test
public void getStatus_FileNotExisting_returnStatus3() throws Exception {
// arrange
Mockito.doThrow(new FileNotFoundException("UnitTest")).when(readerFactory).createFor(Mockito.any(File.class));
// act
int status = sut.getStatus(ANY_FILE_NAME);
// assert
Assert.assertThat("status",status,CoreMatchers.equalTo(3));
}
#Test
public void getStatus_ValidFile_returnFileContentAsInt() throws Exception {
// arrange
BufferedReader bufferedReader = Mockito.mock(BufferedReader.class);
Mockito.doReturn(bufferedReader).when(readerFactory).createFor(Mockito.any(File.class));
Mockito.doReturn("4711").when(bufferedReader).readLine();
// act
int status = sut.getStatus(ANY_FILE_NAME);
// assert
Assert.assertThat("status",status,CoreMatchers.equalTo(4711));
}
}
You have to use something like this:
#RunWith(PowerMockRunner.class)
#PrepareForTest(tests.class)
public class test {
#Test
public void test() throws Exception {
File fileMock = Mockito.mock(File.class);
PowerMockito.whenNew(File.class).withArguments(Mockito.anyString(), Mockito.anyString()).thenReturn(fileMock);
FolderServiceImpl sut = new FolderServiceImpl sut ();
Mockito.when(fileMock.exists()).thenReturn(true);
sut.getStatus("");
// Your verifications..
}
}
Powermock will mock the File object which is created in the method getStatus of your class. With Mockito.when you can say what is the return value of folderStatusFile.exists() in your code.
EDIT
I have included the following two jars with maven, but you don't need to use maven: https://mvnrepository.com/artifact/org.powermock/powermock-module-junit4/1.4.6 and https://mvnrepository.com/artifact/org.powermock/powermock-api-mockito/1.4.9 and https://mvnrepository.com/artifact/org.mockito/mockito-all/1.10.19

Does reading properties files multiple times consume lots memory?

I have a class which reads a properties file. Please see below.
The method readProperties() is called many times when the application is running, does that mean there is a memory issue here?
public class PropertyReader {
private static Properties configKeyValuePairs = null;
private static String configPropertiesFileName = "Config.properties";
static void readProperties() throws FileNotFoundException, IOException {
configKeyValuePairs = new Properties();
InputStream input = ConfigReader.class
.getResourceAsStream(configPropertiesFileName);
configKeyValuePairs.load(input);
input.close();
}
static String getUserName(){
//return user name which is from the properties file.
}
}
Assuming your properties file never changes, you can do the following:
public class MyApplicationConfiguration {
private static Properties configKeyValuePairs = new Properties();
private static String configPropertiesFileName = "Config.properties";
static {
InputStream input = null;
try {
input = MyApplicationConfiguration.class
.getResourceAsStream(configPropertiesFileName);
configKeyValuePairs.load(input);
} catch (IOException e) {
// Deal with not being able to load config, could be a fatal error!
} finally {
if (input != null) {
input.close();
}
}
}
public static String getUsername() {
// ...
}
// Implement getters for other configuration key-value pairs
// DO NOT let configKeyValuePairs be returned to anyone
}
Load the properties object once, and store it a class member.
I find it hard to believe that you will have memory issues because of it.
If you find out that you do, then you can always comeback and rethink it, but don't prematurely optimize a problem that probably doesn't exist.
Yes, there could be a very big memory problem, depending on whether or not there are calling classes that hold a reference to the newly created properties object.
Try something like this:
public class PropertyReader {
private static Properties configKeyValuePairs = null;
private static final String configPropertiesFileName = "Config.properties";
public static void readProperties() throws FileNotFoundException, IOException {
if(null == configKeyValuePairs){
InputStream input;
synchronized(PropertyReader.class){
try{
configKeyValuePairs = new Properties();
input = PropertyReader.class
.getResourceAsStream(configPropertiesFileName);
configKeyValuePairs.load(input);
}finally{
//this can still throw ioexception!
if(null != input){
input.close();
}
}
}
}
}

Categories