I'm using java.util.resourcebundle to format my JSTL messages and this works fine:
I use the class MessageFormat you can see here. Now I want to encapsulate this to a method that is just getParametrizedMessage(String key, String[]parameters) but I'm not sure how to do it. Now there is quite a lot of work to display just one or two messages with parameters:
UserMessage um = null;
ResourceBundle messages = ResourceBundle.getBundle("messages");
String str = messages.getString("PF1");
Object[] messageArguments = new String[]{nyreg.getNummer()};
MessageFormat formatter = new MessageFormat("");
formatter.applyPattern(messages.getString("PI14"));
String outputPI14 = formatter.format(messageArguments);
formatter.applyPattern(messages.getString("PI15"));
String outputPI15 = formatter.format(messageArguments)
if(ipeaSisFlag)
if(checkIfPCTExistInDB && nyreg.isExistInDB()) {
//um = new ExtendedUserMessage(MessageHandler.getParameterizedMessage("PI15", new String[]{nyreg.getNummer()}) , UserMessage.TYPE_INFORMATION, "Info");
um = new ExtendedUserMessage(outputPI15 , UserMessage.TYPE_INFORMATION, "Info");
…and so on. Now can I move this logic to a static class MessageHandler.getParameterizedMessage that now is not working and looking like this:
private final static String dictionaryFileName="messages.properties";
public static String getParameterizedMessage(String key, String [] params){
if (dictionary==null){
loadDictionary();
}
return getParameterizedMessage(dictionary,key,params);
}
private static void loadDictionary(){
String fileName = dictionaryFileName;
try {
dictionary=new Properties();
InputStream fileInput = MessageHandler.class.getClassLoader().getResourceAsStream(fileName);
dictionary.load(fileInput);
fileInput.close();
}
catch(Exception e) {
System.err.println("Exception reading propertiesfile in init "+e);
e.printStackTrace();
dictionary=null;
}
}
How can I make using my parametrized messages as easy as calling a method with key and parameter?
Thanks for any help
Update
The logic comes from an inherited method that in in the abstract class that this extends. The method looks like:
protected static String getParameterizedMessage(Properties dictionary,String key,String []params){
if (dictionary==null){
return "ERROR";
}
String msg = dictionary.getProperty(key);
if (msg==null){
return "?!Meddelande " +key + " saknas!?";
}
if (params==null){
return msg;
}
StringBuffer buff = new StringBuffer(msg);
for (int i=0;i<params.length;i++){
String placeHolder = "<<"+(i+1)+">>";
if (buff.indexOf(placeHolder)!=-1){
replace(buff,placeHolder,params[i]);
}
else {
remove(buff,placeHolder);
}
}
return buff.toString();
}
I think I must rewrite the above method in order to make it work like a resourcebundle rather than just a dictionary.
Update 2
The code that seems to work is here
public static String getParameterizedMessage(String key, Object [] params){
ResourceBundle messages = ResourceBundle.getBundle("messages");
MessageFormat formatter = new MessageFormat("");
formatter.applyPattern(messages.getString(key));
return formatter.format(params);
}
I'm not really sure what you're trying to achive, here's what I did in the past:
public static final String localize(final Locale locale, final String key, final Object... param) {
final String name = "message";
final ResourceBundle rb;
/* Resource bundles are cached internally,
never saw a need to implement another caching level
*/
try {
rb = ResourceBundle.getBundle(name, locale, Thread.currentThread()
.getContextClassLoader());
} catch (MissingResourceException e) {
throw new RuntimeException("Bundle not found:" + name);
}
String keyValue = null;
try {
keyValue = rb.getString(key);
} catch (MissingResourceException e) {
// LOG.severe("Key not found: " + key);
keyValue = "???" + key + "???";
}
/* Message formating is expensive, try to avoid it */
if (param != null && param.length > 0) {
return MessageFormat.format(keyValue, param);
} else {
return keyValue;
}
}
Related
I am new to OpenTelemetry word. I have created spans for my services separately, but when i am try to combine spans of two different services, using context propogation, I am not able to do it successfully.
I have used following code:
// at client side:
public static void sendContext(String resource) {
TextMapSetter<HttpURLConnection> setter =
new TextMapSetter<HttpURLConnection>() {
#Override
public void set(HttpURLConnection carrier, String key, String value) {
carrier.setRequestProperty(key, value);
}
};
HttpURLConnection transportLayer = null;
String urlString = "http://127.0.0.1:8080" + resource;
try {
URL url = new URL(urlString);
transportLayer = (HttpURLConnection) url.openConnection();
} catch (MalformedURLException ex) {
System.out.println(ex.getMessage());
} catch (IOException e) {
System.out.println(e.getMessage());
}
GlobalOpenTelemetry.getPropagators()
.getTextMapPropagator()
.inject(Context.current(), transportLayer, setter);
}
// at server side:
public static Context getContext(HttpServletRequest request) {
TextMapGetter<HttpServletRequest> getter =
new TextMapGetter<HttpServletRequest>() {
#Override
public String get(HttpServletRequest carrier, String key) {
Enumeration<String> headerNames = carrier.getHeaderNames();
if (headerNames != null) {
while (headerNames.hasMoreElements()) {
String headerName = headerNames.nextElement();
System.out.println("headerNames.nextElement(): " + headerName);
if (headerName.equals(key)) {
String headerValue = request.getHeader(headerName);
System.out.println("headerValue): " + headerValue);
return headerValue;
}
}
}
return null;
}
#Override
public Iterable<String> keys(HttpServletRequest carrier) {
Set<String> set = new HashSet<String>();
Enumeration<String> headerNames = carrier.getHeaderNames();
if (headerNames != null) {
while (headerNames.hasMoreElements()) {
set.add(headerNames.nextElement());
}
}
return set;
}
};
Context extractedContext =
GlobalOpenTelemetry.getPropagators()
.getTextMapPropagator()
.extract(Context.current(), request, getter);
At server, i am not able to get parent span.
Kindly help on this.
You can refer to OpenTelemetry main documentation from here. It contains the context propagation part but I used HttpHeader type getter as the TextMapGetter with the same functionality which shows in the doc and instead of using
Scope scope = extractedContext.makeCurrent()
as the scope to create a child span, better to use directly without the scope,
tracer.spanBuilder(spanName).setParent(extractedContext)
Because sometimes the automated way to propagate the parent span on the current thread does not work fine.
I want my Java Program to return a String response based on if/else conditions but it only responds to the last element in the ArrayList.
I have been working on this for two days without success.
I will appreciate a direction as to what am doing wrongly. Thank You
import java.io.IOException;
import java.util.logging.Logger;
public class ScanUtility implements IScanUtility {
Logger logger = Logger.getLogger("ScanUtility");
private String performHostScan(String nodeName) {
Process OSCmdProcess = null;
Integer exitValue = null;
String OScmd = null;
String exitMessage = null;
String OScmd = new String("/usr/bin/ssh ansible#" + nodeName + " " + "/tmp/openscapscan.bash rheldisa");
try {
OSCmdProcess = Runtime.getRuntime().exec(OScmd);
exitValue = OSCmdProcess.waitFor();
if (exitValue.equals(0)) {
exitMessage = ("Succeeded on" + " " + nodeName);
return exitMessage;
} else {
exitMessage = ("Failed on" + " " + nodeName);
return exitMessage;
}
} catch (IOException ioExcep) {
ioExcep.printStackTrace();
} catch (InterruptedException interExcep) {
interExcep.printStackTrace();
}
return exitMessage;
}
//This method takes an ArrayList of hosts from the servlet controller
// and passes the list to the ScanUtility Method above
//============================================================
public String generateHostName(List<String> addressList){
String statusMessage = null;
for(String nodeName: addressList){
statusMessage = new ScanUtility().performHostScan(nodeName);
}
return statusMessage;
}
}
The problem is that you are overwriting statusMessage on ever iteration of your loop. I believe what you want to do is put all the Strings into an ArrayList<String>.
public ArrayList<String> generateHostName(List<String> addressList){
ArrayList<String> statusMessage = new ArrayList<>();
for(String nodeName: addressList){
statusMessage.add(new ScanUtility().performHostScan(nodeName));
}
return statusMessage;
}
Apparently, you want to return a list of status messages (a status message from each server that you are scanning).
public List<String> getResponsesFromAddresses(List<String> addresses) {
final ScanUtility scanUtility = new ScanUtility();
return addresses.stream()
.map(scanUtility::performHostScan)
.collect(Collectors.toList());
}
The method name is misleading. I have changed it to getResponsesFromAddresses - that is what the method actually does.
Try this:
public List<String> generateHostName(List<String> addressList){
List<String> statusMessages = new ArrayList<>();
for(String nodeName: addressList){
statusMessages.add(new ScanUtility().performHostScan(nodeName));
}
return statusMessages;
}
Has anyone an idea about what is wrong with my attempt to call a method from a C# dll in my Java code?
Here is my example:
Java code:
public class CsDllHandler {
public interface IKeywordRun extends Library {
public String KeywordRun(String action, String xpath, String inputData,
String verifyData);
}
private static IKeywordRun jnaInstance = null;
public void runDllMethod(String action, String xpath, String inputData,
String verifyData) {
NativeLibrary.addSearchPath(${projectDllName},
"${projectPath}/bin/x64/Debug");
jnaInstance = (IKeywordRun) Native.loadLibrary(
${projectDllName}, IKeywordRun.class);
String csResult = jnaInstance.KeywordRun(action, xpath, inputData,
verifyData);
System.out.println(csResult);
}
}
And in C#:
[RGiesecke.DllExport.DllExport]
public static string KeywordRun(string action, string xpath, string inputData, string verifyData) {
return "C# here";
}
The Unmanaged Exports nuget should be enough for me to call this method (in theory) but I have some strange error:
Exception in thread "main" java.lang.Error: Invalid memory access
at com.sun.jna.Native.invokePointer(Native Method)
at com.sun.jna.Function.invokePointer(Function.java:470)
at com.sun.jna.Function.invokeString(Function.java:651)
at com.sun.jna.Function.invoke(Function.java:395)
at com.sun.jna.Function.invoke(Function.java:315)
at com.sun.jna.Library$Handler.invoke(Library.java:212)
at com.sun.proxy.$Proxy0.KeywordRun(Unknown Source)
at auto.test.keywords.utils.CsDllHandler.runDllMethod(CsDllHandler.java:34)
at auto.test.keywords.runner.MainClass.main(MainClass.java:24)
Well, after another day of research and "trial and error" I have found the cause of my problem and a solution.
The cause was that my C# dll had a dependency on log4net.dll. For running a static method from a standalone C# dll the code from the question is all you need.
The solution for using C# dll with dependencies is to create another dll with no dependency and to load the original dll in this adapter with reflection. In Java you should load the adapter dll with jna and call any exported method. I was able not only to execute methods from the adapter but also to configure log4net with reflection and Java
Here is my code:
(C#)
public class CSharpDllHandler {
private static Logger log = Logger.getLogger(CSharpDllHandler.class);
public interface IFrameworkAdapter extends Library {
public String runKeyword(String action, String xpath, String inputData,
String verifyData);
public String configureLog4net(String log4netConfigPath);
public String loadAssemblies(String frameworkDllPath,
String log4netDllPath);
}
private static IFrameworkAdapter jnaAdapterInstance = null;
private String jnaSearchPath = null;
public CSharpDllHandler(String searchPath) {
this.jnaSearchPath = searchPath;
// add to JNA search path
System.setProperty("jna.library.path", jnaSearchPath);
// load attempt
jnaAdapterInstance = (IFrameworkAdapter) Native.loadLibrary(
"FrameworkAdapter", IFrameworkAdapter.class);
}
public String loadAssemblies(String frameworkDllPath, String log4netDllPath) {
String csResult = jnaAdapterInstance.loadAssemblies(frameworkDllPath,
log4netDllPath);
log.debug(csResult);
return csResult;
}
public String runKeyword(String action, String xpath, String inputData,
String verifyData) {
String csResult = jnaAdapterInstance.runKeyword(action, xpath,
inputData, verifyData);
log.debug(csResult);
return csResult;
}
public String configureLogging(String log4netConfigPath) {
String csResult = jnaAdapterInstance
.configureLog4net(log4netConfigPath);
log.debug(csResult);
return csResult;
}
public String getJnaSearchPath() {
return jnaSearchPath;
}
}
In the main method just use something like this:
CSharpDllHandler dllHandler = new CSharpDllHandler(
${yourFrameworkAdapterDllLocation});
dllHandler.loadAssemblies(
${yourOriginalDllPath},${pathToTheUsedLog4netDllFile});
dllHandler.configureLogging(${log4net.config file path});
dllHandler.runKeyword("JAVA Action", "JAVA Xpath", "JAVA INPUT",
"JAVA VERIFY");
dllHandler.runKeyword("JAVA Action2", "JAVA Xpath2", "JAVA INPUT2",
"JAVA VERIFY2");
In C# I have the desired methods on the original dll:
public static string KeywordRun(string action, string xpath, string inputData, string verifyData) {
log.Debug("Action = " + action);
log.Debug("Xpath = " + xpath);
log.Debug("InputData = " + inputData);
log.Debug("VerifyData = " + verifyData);
return "C# UserActions result: "+ action+" "+xpath+" "+inputData+" "+verifyData;
}
and all the magic is in the DLL Adapter:
namespace FrameworkAdapter {
[ComVisible(true)]
public class FwAdapter {
private const String OK="OK";
private const String frameworkEntryClassName = "${nameOfTheDllClass with method to run }";
private const String log4netConfiguratorClassName = "log4net.Config.XmlConfigurator";
private static Assembly frameworkDll = null;
private static Type frameworkEntryClass = null;
private static MethodInfo keywordRunMethod = null;
private static Assembly logDll = null;
private static Type logEntryClass = null;
private static MethodInfo logConfigureMethod = null;
private static String errorMessage = "OK";
[RGiesecke.DllExport.DllExport]
public static string loadAssemblies(string frameworkDllPath, string log4netDllPath) {
try {
errorMessage = LoadFrameworkDll(frameworkDllPath, frameworkEntryClassName);
LoadFrameworkMethods("KeywordRun", "Setup", "TearDown");
errorMessage = LoadLogAssembly(log4netDllPath, log4netConfiguratorClassName);
if (errorMessage.CompareTo(OK) == 0)
errorMessage = LoadLogMethods("Configure");
}
catch (Exception e) {
return e.Message;
}
return errorMessage;
}
[RGiesecke.DllExport.DllExport]
public static string configureLog4net(string log4netConfigPath) {
if (errorMessage.CompareTo("OK") == 0) {
StringBuilder sb = new StringBuilder();
sb.AppendLine("Try to configure Log4Net");
try {
FileInfo logConfig = new FileInfo(log4netConfigPath);
logConfigureMethod.Invoke(null, new object[] { logConfig });
sb.AppendLine("Log4Net configured");
}
catch (Exception e) {
sb.AppendLine(e.InnerException.Message);
}
return sb.ToString();
}
return errorMessage;
}
[RGiesecke.DllExport.DllExport]
public static string runKeyword(string action, string xpath, string inputData, string verifyData) {
StringBuilder sb = new StringBuilder();
object result = null;
try {
result = keywordRunMethod.Invoke(null, new object[] { action, xpath, inputData, verifyData });
sb.AppendLine(result.ToString());
}
catch (Exception e) {
sb.AppendLine(e.InnerException.Message);
}
return sb.ToString();
}
private static String LoadFrameworkDll(String dllFolderPath, String entryClassName) {
try {
frameworkDll = Assembly.LoadFrom(dllFolderPath);
Type[] dllTypes = frameworkDll.GetExportedTypes();
foreach (Type t in dllTypes)
if (t.FullName.Equals(entryClassName)) {
frameworkEntryClass = t;
break;
}
}
catch (Exception e) {
return e.InnerException.Message;
}
return OK;
}
private static String LoadLogAssembly(String dllFolderPath, String entryClassName) {
try {
logDll = Assembly.LoadFrom(dllFolderPath);
Type[] dllTypes = logDll.GetExportedTypes();
foreach (Type t in dllTypes)
if (t.FullName.Equals(entryClassName)) {
logEntryClass = t;
break;
}
}
catch (Exception e) {
return e.InnerException.Message;
}
return OK;
}
private static String LoadLogMethods(String logMethodName) {
try {
logConfigureMethod = logEntryClass.GetMethod(logMethodName, new Type[] { typeof(FileInfo) });
}
catch (Exception e) {
return e.Message;
}
return OK;
}
private static void LoadFrameworkMethods(String keywordRunName, String scenarioSetupName, String scenarioTearDownName) {
///TODO load the rest of the desired methods here
keywordRunMethod = frameworkEntryClass.GetMethod(keywordRunName);
}
}
}
Running this code will provide all the logged messages from the original C# DLL to the Java console output (and to a file if configured). In a similar way, we can load any other needed dll files for runtime.
Please forgive my [very probable wrong] way of doing things in C# with reflection, I'm new to this language.
I have a large number of axis generated objects from several WSDLs, I need a generic solution to store the objects in xml format in the database, but also load them back in java when needed.
This is what I've made so far:
private String serializeAxisObject(Object obj) throws Exception {
if (obj == null) {
return null;
}
StringWriter outStr = new StringWriter();
TypeDesc typeDesc = getAxisTypeDesc(obj);
QName qname = typeDesc.getXmlType();
String lname = qname.getLocalPart();
if (lname.startsWith(">") && lname.length() > 1)
lname = lname.substring(1);
qname = new QName(qname.getNamespaceURI(), lname);
AxisServer server = new AxisServer();
BeanSerializer ser = new BeanSerializer(obj.getClass(), qname, typeDesc);
SerializationContext ctx = new SerializationContext(outStr,
new MessageContext(server));
ctx.setSendDecl(false);
ctx.setDoMultiRefs(false);
ctx.setPretty(true);
try {
ser.serialize(qname, new AttributesImpl(), obj, ctx);
} catch (final Exception e) {
throw new Exception("Unable to serialize object "
+ obj.getClass().getName(), e);
}
String xml = outStr.toString();
return xml;
}
private Object deserializeAxisObject(Class<?> cls, String xml)
throws Exception {
final String SOAP_START = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"><soapenv:Header /><soapenv:Body>";
final String SOAP_START_XSI = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"><soapenv:Header /><soapenv:Body>";
final String SOAP_END = "</soapenv:Body></soapenv:Envelope>";
Object result = null;
try {
Message message = new Message(SOAP_START + xml + SOAP_END);
result = message.getSOAPEnvelope().getFirstBody()
.getObjectValue(cls);
} catch (Exception e) {
try {
Message message = new Message(SOAP_START_XSI + xml + SOAP_END);
result = message.getSOAPEnvelope().getFirstBody()
.getObjectValue(cls);
} catch (Exception e1) {
throw new Exception(e1);
}
}
return result;
}
private TypeDesc getAxisTypeDesc(Object obj) throws Exception {
final Class<? extends Object> objClass = obj.getClass();
try {
final Method methodGetTypeDesc = objClass.getMethod("getTypeDesc",
new Class[] {});
final TypeDesc typeDesc = (TypeDesc) methodGetTypeDesc.invoke(obj,
new Object[] {});
return (typeDesc);
} catch (final Exception e) {
throw new Exception("Unable to get Axis TypeDesc for "
+ objClass.getName(), e);
}
}
I have fixed it, I will leave this here if anyone else needs to use it
Have fun.
I have fixed it, I will leave this here if anyone else needs to use it. See the updated version.
Thank you
I need to encode a URL using HTTP GET request in Blackberry. Can any one help me find how do I achieve this.
Whyt don't you use RIM's URLEncodedPostData?
private String encodeUrl(String hsURL) {
URLEncodedPostData urlEncoder = new URLEncodedPostData("UTF-8", false);
urlEncoder.setData(hsURL);
hsURL = urlEncoder.toString();
return hsURL;
}
here you go ;^)
public static String URLencode(String s)
{
if (s!=null) {
StringBuffer tmp = new StringBuffer();
int i=0;
try {
while (true) {
int b = (int)s.charAt(i++);
if ((b>=0x30 && b<=0x39) || (b>=0x41 && b<=0x5A) || (b>=0x61 && b<=0x7A)) {
tmp.append((char)b);
}
else {
tmp.append("%");
if (b <= 0xf) tmp.append("0");
tmp.append(Integer.toHexString(b));
}
}
}
catch (Exception e) {}
return tmp.toString();
}
return null;
}
use the class provided by w3. Here is the download link
the reply using "URLEncodedPostData" above is incorrect.
Corrected sample:
public static String encodeUrl(Hashtable params)
{
URLEncodedPostData urlEncoder = new URLEncodedPostData("UTF-8", false);
Enumeration keys = params.keys();
while (keys.hasMoreElements()) {
String name = (String) keys.nextElement();
String value = (String) params.get(name);
urlEncoder.append(name, value);
}
String encoded = urlEncoder.toString();
return encoded;
}
Cheers!