This is my first question I hopefully don't make any terrible mistake.
Assuming no SecurityManager is preventing me from doing this :
public static void main(String[] args) {
String str = "1";
System.out.println("str value before invoke fillStringValueWithX method: " + str);
fillStringValueWithX(str);
System.out.println("str value before invoke fillStringValueWithX method: " + str);
}
private static void fillStringValueWithX(String str) {
if (str != null) {
try {
Field fieldValue = String.class.getDeclaredField("value");
fieldValue.setAccessible(true);
char[] charValue = (char[]) fieldValue.get(str);
Arrays.fill(charValue, 'x');
fieldValue.setAccessible(false);
} catch (Exception e) {}
}
}
If the size of the string is 1 (the example above) the JVM crash (the crash dump shows an EXCEPTION_ACCESS_VIOLATION error) however if the size of the string is greater than 1 this code snippet works for me.
Note: I assume that the appropiate use for setting a field's value via reflection is using valueField.set(obj, value) Field method but I want to know why the JVM crash...
Thanks
Patient: Doctor, doctor, it hurts when I do this (bangs arm with hammer).
Doctor: Don't do that then.
You really shouldn't be trying to mess with the contents of a string. Strings are designed to be immutable. Now I dare say it's a JVM bug that it crashes so dramatically (it doesn't on my box, btw - it would be useful if you'd tell us which operating system and JVM version you're using) but the simple answer is not to try to go behind the system's back.
it looks like that array of chars for "1" and a number of other interned Strings (like "true", "false", "root", "class", etc) cannot be changed in Windows JVM. I.e. you cannot assign new values to array elements. But you can assign new array for that String object. Example
Related
Just had a look at the "new" C# 8.0 Features
So I tried to rewrite the following code
private static void RunExample(ExampleCode exampleCode)
{
switch(exampleCode)
{
case ExampleCode.DefaultInterfaceMethod:
RunDefaultInterfaceMethodExample();
break;
case ExampleCode.PatternMatchingEnhancements:
RunPatternMatchingEnhancementsExample();
break;
}
}
to this:
private static void RunExample(ExampleCode exampleCode)
{
exampleCode switch
{
ExampleCode.DefaultInterfaceMethod => RunDefaultInterfaceMethodExample(),
ExampleCode.PatternMatchingEnhancements => RunPatternMatchingEnhancementsExample()
};
}
However, I am getting the following compile error:
Only assignment, call, increment, decrement, await, and new object
expressions can be used as a statement.
How can I rewrite this in the new syntax?
As pointed in the comments the new switch based pattern matching is expecting result to be returned.
In F# because everything is an expression, the void type is actually a valid return type for an expression and this would have worked.
In case like yours i think it is best to use the old code, but if you really want to use the new syntax you can do something like this:
Action methodToExecute = exampleCode switch
{
ExampleCode.DefaultInterfaceMethod => RunDefaultInterfaceMethodExample,
ExampleCode.PatternMatchingEnhancements => RunPatternMatchingEnhancementsExample,
_ => throw new NotImplementedException()
};
methodToExecute();
(this will work only if the methods you are executing for each case have the same definitions)
It is good practice to use exhaustive pattern, this is why i am using the last case with the underscore.
In C# enum values are compiled to integers and even if your switch handles all enum labels the compiler still does not know you have handled all cases and when you add new label to the enum you won't have proper warrning that you are have unhandled case.
Whenever you are using enums it is best to use default case where all unhandled cases will fall in.
Often, I work on Java EE application. Today I'm facing an issue: serialize Collections in servlet context. In my case, my app contains a Servlet Context Listener and many servlets.
The context listener load a ConcurrentHashMap containing several lists of products at initialisation and a task scheduler to refresh this list.
The servlets are supposed to access the right list, based on user provided parameters.
Here the code of my contextInitialized Listener:
public void contextInitialized(ServletContextEvent event) {
app = event.getServletContext();
myMap = new ConcurrentHashMap<String, Catalog>();
myMap.put("FR", new Catalog());
myMap.put("UK", new Catalog());
app.setAttribute("catalogue", myMap);
scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate(new AutomateRefresh(), 0, 60, TimeUnit.MINUTES);
}
In order to show my problem, i created a servlet that display everything which is a boolean or a ConcurrentHashMap in context
I'm not surprised to find this kind of results:
javax.servlet.context.tempdir is equal to...
Working is equal to... true
org.apache.catalina.resources is equal to...
org.apache.tomcat.InstanceManager is equal to...
org.apache.catalina.jsp_classpath is equal to...
javax.websocket.server.ServerContainer is equal to...
org.apache.jasper.compiler.TldCache is equal to...
catalogue is equal to...
org.apache.tomcat.JarScanner is equal to...
As you can see, my two custom keys (the boolean Working and the ConcurrentHashMap catalogue) exists. But catalogue is empty when not accessed inside the Listener.
I found that:
The serialization form of java.util.HashMap doesn't serialize the buckets themselves, and the hash code is not part of the persisted state.
Source: Serializing and deserializing a map with key as string
For many projects a serializable and thread-safe collection is useful. I am probably not the only one who is looking for that (see the amount of topic about servlet context).
ConcurrentHashMap is thread-safe but I am unable to retrieve my data in other servlet (in the same app). Is there an implementation of Collection which is thread-safe and serializable (due to WebLogic server policy) ? Or am I using it in a wrong way ?
EDIT: Code of "Display context servlet"
public void doGet( HttpServletRequest request, HttpServletResponse response ) throws ServletException, IOException{
System.out.println("List of all values in the context:");
Enumeration<?> e = getServletContext().getAttributeNames();
while (e.hasMoreElements())
{
String name = (String) e.nextElement();
System.out.print("\n" + name + " is equal to... ");
// Get the value of the attribute
Object value = this.getServletContext().getAttribute(name);
if (value instanceof ConcurrentHashMap) {
ConcurrentHashMap<String, Catalog> map = (ConcurrentHashMap<String, Catalog>) value;
Iterator<Entry<String, Catalog>> it = map.entrySet().iterator();
while (it.hasNext()) {
ConcurrentHashMap.Entry<String, Catalog> entry = (ConcurrentHashMap.Entry<String, Catalog>)it.next();
System.out.print("\t" + entry.getKey() + "=" + entry.getValue());
}
} else if (value instanceof Boolean) {
System.out.print((Boolean)value);
}
}
}
EDIT2: Like BalusC suggested the HashMap maybe null (a rookie mistake ?).
Here the task code. The task is in the Listener. The Listener initialize the HashMap with new empty object. The task refresh the objects when webapp starts and then every hour.
public class AutomateRefresh implements Runnable {
public void run() {
System.out.println("Scheduler trigger");
if(app.getAttribute("catalogue") instanceof ConcurrentHashMap){
myMap = (ConcurrentHashMap<String, Catalog>) app.getAttribute("catalogue");
//Autorefresh
Iterator<Entry<String, Catalog>> it = myMap.entrySet().iterator();
while (it.hasNext()) {
ConcurrentHashMap.Entry<String, Catalog> entry = (ConcurrentHashMap.Entry<String, Catalog>)it.next();
((Catalog)entry.getValue()).setValid(false);//Set as not valid anymore for further request
try {
((Catalog)entry.getValue()).refreshdb((String) entry.getKey());//TODO rework to use REST API
} catch (SQLException e) {
e.printStackTrace();
}
it.remove(); // avoids a ConcurrentModificationException
app.setAttribute("catalogue", myMap);
app.setAttribute("Working", true);
System.out.println((String)entry.getKey() + " = " + (Catalog)entry.getValue());
}
}
else{
System.out.println("Catalogue is not an instance of ConcurrentHashMap as expected.");
app.setAttribute("Working", false);
}
}
}
When the task triggered, for each Catalog stored in the Context, the task update the data stored by them. It also display data in console.
Results:
Refresh Catalog for UK with DB
UK = Catalog [list size is : 0 valid=true, lastToken=notoken]
Refresh Catalog for FR with DB
FR = Catalog [list size is : 30 valid=true, lastToken=notoken]
Catalog is a class with an ArrayList, a boolean and a String. Everything seems correct: UK is supposed to be empty but not null and FR is supposed to contains 30 products.
I still can not access this data in other servlets.
I found the origin of the problem, a rookie mistake as expected:
I tried to update this way, assuming it would have updated the object directly in the ConcurrentHashMap
((Catalog)entry.getValue()).refreshdb((String) entry.getKey());
I replace it by:
Catalog myCatalog = (Catalog)entry.getValue();
myCatalog.refreshdb((String) entry.getKey());
myMap.put((String)entry.getKey(), myCatalog);
And it works now.
I still don't know why my objects were accessible from the listener, they are not supposed to work that way. Maybe a strange behavior from my server ? Anyway, this issue is fixed.
Thanks to BalusC for his help.
I am incredibly new to .NET and Mono. I have a .NET 4 application that I am trying to run locally, and I'm getting a compilation error when I try to run it (using xps4 on Ubuntu). At the end of the stacktrace it says:
/tmp/jeremy-temp-aspnet-0/3b8f3547/App_Web_635c7158_48.cs(32,21): error CS0246: The type or namespace name `bool' could not be found. Are you missing a using directive or an assembly reference?
Does that mean that it doesn't recognize the boolean type? A Google search wasn't much help.
Update - Here's the code:
public virtual #bool ShowRecentPlans {
get {
return ((#bool)(this.GetPropertyValue("ShowRecentPlans")));
When you prefix an identifier (like a type name) with #, you're telling the compiler that, even though it looks like a reserved word, it refers to something defined in your program.
Unless you have something defined somewhere like
public class #bool
{
...
}
then this isn't going to work.
Try
public virtual bool ShowRecentPlans {
get {
return (bool)(this.GetPropertyValue("ShowRecentPlans"));
}
}
For instance, if you wanted to use the keyword new as an identifier, you could:
int new = 5; /// error!
int #new = 5; /// compiles
# is of course also used to tell the compiler how a string should be interpreted.
// throws an error because \p and \m look like formatting sequences
var path = "c:\pub\myFile.txt";
// compiles
var path = #"c:\pub\myFile.txt";
Also, I just have to ask: what made you use #bool instead of bool to start with?
(And, for the record, using a keyword as an identifier is a very, very bad idea.)
Your return type should be bool instead of #bool.
So, there are a wealth of Flex articles online about how to handle a .NET WebMethod that returns a DataSet or DataTable. Here is an example:
Handling web service results that contain .NET DataSets or DataTables
So, I know how to use result.Tables.<tablename>.Rows and the like. But what I cannot seem to figure out or find online is how to go the other direction - a method to pass objects or tables back to the .NET Webservice from Flex, without stooping to passing XML as a string, or making huge web service methods that have one parameter for each property/column of the object being stored. Surely others, smarter than I, have tackled this issue.
I am using ASP.NET 2.0 Typed DataSets, and it would be really nice if I could just pass one object or array of objects from Flex to the web service, populate my Typed DataTable, and do an Update() through the corresponding typed TableAdapter. My dream would be a [WebMethod] something like one of these:
public void SaveObject(TypedDataTable objToSave) { ... }
public void SaveObject(TypedDataSet objToSave) { ... }
I've had the typed datatables saving to the database, I know how to do that part and even a few tricks, but we had XML being passed back-and-forth as a string - eww. I'm trying to get to a more object-based approach.
The best object based approach is AMF. I assume its probably a bit late in your your development cycle to change your integration layer, but otherwise I dont know of a way to get around marshalling your object(s) back into XML or separating them out into their primitive components.
For .NET implementations of AMF check out:
FlourineFX(FOSS)
WebORB for .NET
Its amazing how easy things become once AMF is used, for example using the Mate MVC framework and an AMF call passing a complex object to the server looks something like this:
<mate:RemoteObjectInvoker instance="yourWebservice" method="saveComplexObject" showBusyCursor="true" >
<mate:resultHandlers>
<mate:CallBack method="saveComplexObjectSuccess" arguments="{[resultObject]}" />
</mate:resultHandlers>
<mate:faultHandlers>
<mate:MethodInvoker generator="{DataManager}" method="presentFault" arguments="{fault}" />
</mate:faultHandlers>
</mate:RemoteObjectInvoker>
With result and fault handlers being optional.
The direction I ended up going was close to what I hoped was possible, but is "hack-ish" enough that I would consider SuperSaiyen's suggestion to use AMF/ORM a better solution for new/greenfield projects.
For sake of example/discussion, let's say I am working with a Person table in a database, and have a typed DataSet called PeopleDataSet that has PersonTableAdapter and PersonDataTable with it.
READ would look like this in .NET web service:
[WebMethod]
public PeopleDataSet.PersonDataTable GetAllPeople() {
var adapter = new PersonTableAdapter();
return adapter.GetData();
}
... which in Flex would give you a result Object that you can use like this:
// FLEX (AS3)
something.dataProvider = result.Tables.Person.Rows;
Check out the link I put in the question for more details on how Flex handles that.
CREATE/UPDATE - This is the part I had to figure out, and why I asked this question. The Flex first this time:
// FLEX (AS3)
var person:Object = {
PersonID: -1, // -1 for CREATE, actual ID for UPDATE
FirstName: "John",
LastName: "Smith",
BirthDate: "07/19/1983",
CreationDate: "1997-07-16T19:20+01:00" // need W3C DTF for Date WITH Time
};
_pplWebSvcInstance.SavePerson(person); // do the web method call
(For handling those W3C datetimes, see How to parse an ISO formatted date in Flex (AS3)?)
On the .NET web service side then, the trick was figuring out the correct Type on the web method's parameter. If you go with just Object, then step into a call with a debugger, you'll see .NET figures it is a XmlNode[]. Here is what I figured out to do:
[WebMethod]
public int SavePerson(PeopleDataSet p) {
// Now 'p' will be a PeopleDataSet with a Table called 'p' that has our data
// row(s) (just row, in this case) as string columns in random order.
// It WILL NOT WORK to use PeopleDataSet.PersonDataTable as the type for the
// parameter, that will always result in an empty table. That is why the
// LoadFlexDataTable utility method below is necessary.
var adapter = new PersonTableAdapter();
var tbl = new PeopleDataSet.PersonDataTable();
tbl.LoadFlexDataTable(p.Tables[0]); // see below
// the rest of this might be familiar territory for working with DataSets
PeopleDataSet.PersonRow row = tbl.FirstOrDefault();
if (row != null) {
if (row.PersonID > 0) { // doing UPDATE
row.AcceptChanges();
row.SetModified();
}
else { // doing CREATE
row.CreationDate = DateTime.UtcNow; // set defaults here
row.IsDeleted = false;
}
adapter.Update(row); // database call
return row.PersonID;
}
return -1;
}
Now, the kluge utility method you saw called above. I did it as extension method, that is optional:
// for getting the Un-Typed datatable Flex gives us into our Typed DataTable
public static void LoadFlexDataTable(this DataTable tbl, DataTable flexDataTable)
{
tbl.BeginLoadData();
tbl.Load(flexDataTable.CreateDataReader(), LoadOption.OverwriteChanges);
tbl.EndLoadData();
// Probably a bug, but all of the ampersand (&) in string columns will be
// unecessarily escaped (&) - kluge to fix it.
foreach (DataRow row in tbl.Rows)
{
row.SetAdded(); // default to "Added" state for each row
foreach (DataColumn col in tbl.Columns) // fix & to & on string columns
{
if (col.DataType == typeof(String) && !row.IsNull(col))
row[col] = (row[col] as string).Replace("&", "&");
}
}
}
I have a list of error codes I need to reference, kinda like this:
Code / Error Message
A01 = whatever error
U01 = another error
U02 = yet another error type
I get the Code returned to me via a web service call and I need to display or get the readable error. So I need a function when passed a Code that returns the readable description. I was just going to do a select case but thought their might be a better way. What is the best way / most effieient way to do this?
Use a Dictionary, (in C#, but the concept and classes are the same):
// Initialize this once, and store it in the ASP.NET Cache.
Dictionary<String,String> errorCodes = new Dictionary<String,String>();
errorCodes.Add("A01", "Whatever Error");
errorCodes.Add("U01", "Another Error");
// And to get your error code:
string ErrCode = errorCodes[ErrorCodeFromWS];
You would use a dictionary. A dictionary uses a hashmap internally for performance, so it is good in that regard. Also, because you want this to go as quickly as possible by the sounds of it, I would statically initialize it in its own class instead of, for example, in an XML file or slimier. You would probably want something like:
public static class ErrorCodes
{
private static Dictonary<string, string> s_codes = new Dicontary<string, string>();
static ErrorCodes()
{
s_codes["code"] = "Description";
s_codes["code2"] = "Description2";
}
public static string GetDesc(string code)
{
return s_codes[code];
}
}
That way, if you wanted to move the back end to a file instead of being static, then you could.