how to update jar class files through programming - java

I have a jar file which consisting of multiple class files.
Main class file's java file is like
class Main
{
public void setUserType()
{
String utype="user";
}
}
now i want to update the Main class file with usertype "user" to "admin" and recreate the jar file
can you suggest me how can i do this so that the new jar file should have usertype "admin"
These changes should be done through programming not through editor like netbeans or eclipse

Instead of hardcoding things, you should define your code to accept properties either via property file or via environment/System property or command line argument when you start your application like below:
class Main {
public void setUserType(String value) {
String utype=value;//or use System.getProperty("value");if you used -Dvalue=admin in command line for example.
}
public static void main(String args[]) {//see main accepts command line argument
if (args.length == 0) {
throw new IllegalArgumentException("Required parameters are missing");
}
Main main = new Main();
main(args[0]);//just pass whatever you pass as system parameter when you start your application
//if you dont want to pass string across multiple methods and classes just use System.setProperty("value", args[0]); and use it like System.getProperty("value") to access it from anywhere without actually passing this string across.
}
}
And run it with user/admin as you like:
java Main admin
java Main user

Related

Run -jar with args and use args in Spring

I need to run jar with static parameter, for example, java -jar myapp-1.0.0.jar /path/static/myfolder, and use this path "/path/static/myfolder" in my code. So, I know how to get this parameters in PSVM (String..args), but how to get it in Spring? Is there annotation for this or may be in properties file>
For example: java -jar -Dtest=abcd myapp-1.0.0.jar.
You can use System.getProperty("test") to get value.
-D{parameter} needs to be before that jar
It is really answer for my question:
create special #Component that implements CommandLineRunner and override method Run, like this:
#Component public class StartupPrintRunner implements CommandLineRunner {
private String folder;
#Override public void run(String... args) throws Exception {
this.folder = Arrays.deepToString(args); }
}
Inject bean StartupPrintRunner where you need and get parameters. It returns String looks like an array: [parameter1, parameter2.., parameter n] and we can parse it to get necessary paarameter.

java.lang.IllegalArgumentException when reading from string

In my project I want to read from string my package name but I got following error.
before I change may code it was like that:
static {
sURLMatcher.addURI("com.nooshindroid.yastashir2.model", "alarm", ALARMS);
sURLMatcher.addURI("com.nooshindroid.yastashir2.model", "alarm/#", ALARMS_ID);
}
In my application class I get the like this:
public static String context;
#Override
public void onCreate() {
context = getApplicationContext().getResources().getString(R.string.package_app);
}
and when I change it like this :
static {
sURLMatcher.addURI(AlarmApplication.context+".model", "alarm", ALARMS);
sURLMatcher.addURI(AlarmApplication.context+".model", "alarm/#", ALARMS_ID);
}
and here is my error:
Unable to create application com.nooshindroid.yastashir2.AlarmApplication: java.lang.IllegalArgumentException: Unknown URL content://com.nooshindroid.yastashir2.model/alarm
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4809)
at android.app.ActivityThread.access$1600(ActivityThread.java:154)
Code in the static initialisation block runs before your Application's onCreate. So your context field is still null when you add URIs to the matcher.
Can you maybe instead use BuildConfig.APPLICATION_ID + ".model" in your static initialisation? BuildConfig fields are written at build time, so will be available in the static initialisation block. If APPLICATION_ID doesn't suit your needs, you can always add a custom build config field in your build.gradle file.

How to invoke a Java class of another Jar file?

I would like to receive the results dynamically invoke a class in another jar.
For example,
'A' directory in a file named A.jar.
'B' directory in a file named B.jar.
I want to dynamically invoke a class of A.jar file to B.jar file.
This is the main class of A.jar file.
Socket and RMI are not considered because the message exchange technology.
Main Class (B.jar)
public class main {
public static void main(String[] args) {
//It dynamically creates an object of a Message Class in A.jar.
//And it invoke the getMessage function.
//And Save the return value.
}}
Message Class (A.jar)
public class message{
public String getMessage(){
return "Hello!";
}
}
First, you need to dynamically create an instance of the given class:
Class<?> clazz = Class.forName("message");
Object messageObj = clazz.newInstance();
This assumes that the .jar file which contains the message class is on the classpath so that the Java runtime is able to find it. Otherwise, you need to manually load the jar file through a class loader, e.g. like in How should I load Jars dynamically at runtime?. Assumed that your A.jar file which contains the message class is located at c:\temp\A.jar, you can use something like
URLClassLoader child = new URLClassLoader (
new URL[] {new URL("file:///c:/temp/A.jar")}, main.class.getClassLoader());
Class<?> clazz = Class.forName("message", true, child);
to load the jar file and load the message class from it.
In both cases, you can then retrieve the method from the class and invoke it on the created instance:
Method getMessage = clazz.getMethod("getMessage");
String result = (String) getMessage.invoke(messageObj);

Pass parameters to JUnit test from the TestSuite class

I want to create 2 JUnit TestSuites. They both utilize the same test classes, but they should each use different parameters. For example, in test suite A, I want my data to be collected from file A and to be written to database A. In test suite B, I want my data to be collected from file B and to be written to databaseB.
The reason I use testSuites for this is because:
I can put all the specific parameters in the testsuite classes
I can reuse the testclasses
I can choose which testsuite to run. I do not want all tests to always run with all possible paramaters!
The problem is I cannot really pass the parameters. I understand the way the Parameterized class works with JUnit, but it does not allow point 3 in the list above. If I use the code below it will run my test class with both databse connections, which is not what I want to achieve.
#RunWith(value = Parameterized.class)
public class TestCheckData
{
private File file;
private DatabaseSource databaseSource;
public TestCheckData(File file, DatabaseSource databaseSource)
{
this.file = file;
this.databaseSource = databaseSource;
}
#Parameters
public static Iterable<Object[]> data1()
{
return Arrays.asList(new Object[][]
{
{ TestSuiteA.DATA_FILE_A, TestSuite1.DATABASE_A },
{ TestSuiteB.DATA_FILE_B, TestSuite1.DATABASE_B }
});
}
I already find some way of passing configurations in a spring context in this question, but I'm not using any special framework.
Well, this would be a little unconventional, but you could add a different Test class to the beginning of each suite run that would set the parameters you want to use for that test. So you'd have classes like:
public abstract class StaticParameters {
public static File dataFileToUse = null;
public static DatabaseSource databaseToUse = null;
}
public class Suite1Params extends StaticParameters {
#BeforeClass
public static void setParams() {
dataFileToUse = DATA_FILE_A;
databaseToUse = DATABASE_A;
}
}
public class Suite2Params extends StaticParameters {
#BeforeClass
public static void setParams() {
dataFileToUse = DATA_FILE_B;
databaseToUse = DATABASE_B;
}
}
Then you'd just make Suite1Params or Suite2Params the first in your suite list. You might have to add a fake #Test entry to the params classes, I'm not sure if the Suite runner requires that.
You could modify the tests so that they get the parameters from a config file. This way you would always only have 1 Suite.
The path of the config file can be looked up via a System property.
Then on the invocation of the test suite, you could pass in a different config file by changing the property using the -D option on the JVM.
So for example if you named the proprerty env.properties then your command would be:
%java -Denv.properties=prod.config runMyTests
or
%java -Denv.properties=dev.config runMyTests
etc

only some methods accessible in jar file

I got a java class from which I created a jar file to access the class in another project.
the class looks like this
public class RunMain {
private ArgumentObject argObject = null;
private String outputFile = null;
private SimObject simObject = null;
public RunMain() {
}
public RunMain(String file) {
outputFile = file;
}
public static void main(String[] args) throws Exception {
new RunMain().doMain(args);
}
public void testMethod(){
}
public void blaMethod(){
}
public SimObject getResults(){
return simObject;
}
public void doMain(String[] args) throws Exception {
// do some stuff
}
// write term and doc vectors to bin files
void writeVectorStore() throws Exception{
// do some stuff
}
}
My problem is, that when I now wanna access the methods in another project I can only call the main method or the doMain method.
RunMain run = new RunMain();
run.doMain(arguments);
this works fine
SimObject simObject = run.getResults();
this is marked red with "The method getResults() is undefined for the type RunMain"
Does someone have an idea why this is happening?
I have two ideas:
The jar file contains an earlier version of the compiled class.
You use an earlier version of the jar file.
But it is not possible that only some public methods of a class are accessible a jar file.
A couple things to check...
Make sure the project using this jar file doesn't have its own version of class RunMain on the classpath. It will "override" RunMain in the jar file. If there is a local version of the class thant doesn't have the method getResults(), well there's your compiler error.
If you've been working on the .jar file for awhile.. better re-build it to make sure the code in there is the latest version. It's possible you created the jar, then added a method, but didn't recreate the jar file. Then make sure the new jar file is being referenced by your project.

Categories

Resources