Suggestion for improving cli wrapper over Apache Commons CLI - java

I have following cli wrapper:
public class CLIUtil
{
// some private variable and other methods
public CLIUtil(final String[] args, final Options commandLineOptions) throws ParseException
{
Validate.notEmpty(args);
Validate.notNull(commandLineOptions);
this.commandLineOptions = commandLineOptions;
this.command = this.parser.parse(this.commandLineOptions, args);
}
public void printHelp(final String executableName)
{
Validate.notEmpty(executableName);
final HelpFormatter formatter = new HelpFormatter();
formatter.printHelp(executableName, this.commandLineOptions);
}
}
Which have following problems:
As we are throwing exception in constructor:
if args as null. There is no way to printHelp.
if args are invalid. There is no way to printHelp.
I am thinking of following solution:
Solution 1:
public CLIUtil(final String executableName, final Options commandLineOptions) throws ParseException
{
Validate.notNull(commandLineOptions);
this.commandLineOptions = commandLineOptions;
this.executableName = executableName;
}
public void parseArgs(final String[] args) throws ParseException
{
Validate.notEmpty(args);
this.command = this.parser.parse(this.commandLineOptions, args);
}
Problem with this solution is:
User need to call set after constructor. so we are letting client to control the flow.
Solution 2:
public CLIUtil(final String executableName, String[] args, final Options commandLineOptions) throws ParseException
{
if (null == args) {
// show help and throw illegal arg
}
Validate.notNull(commandLineOptions);
this.commandLineOptions = commandLineOptions;
this.executableName = executableName;
try {
this.command = this.parser.parse(this.commandLineOptions, args);
} catch (Parse...) {
// catch exception and show error and printhelp followed by
// throw same exception
}
}
Problem with this solution is:
1) Random placement of validation rule.
Do you have a suggestion which solution is better or suggested improvement?

Related

How to get job name from a Sink (or RichFunction in general) w/o using REST API?

As captioned. While getJobId is available from RuntimeContext, job name isn't available.
https://nightlies.apache.org/flink/flink-docs-release-1.13/api/java/org/apache/flink/api/common/functions/RuntimeContext.html
Trying to get it from Configuration doesn't seem to work as well:
#Override
public void open(Configuration parameters) throws Exception {
String jobName = parameters.getString(PipelineOptions.NAME); // this is null
}
This is how we run a standalone sample pipeline:
public static void main(String... args) {
try {
ParameterTool parameterTool = ParameterTool.fromArgs(args);
final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
// some pipeline setup
env.execute("This-is-job-name");
} catch (Exception e) {
// logging
}
Assuming you are passing in the job name as a parameter to the job, you want to set it up like this:
public static void main(String... args) {
ParameterTool parameterTool = ParameterTool.fromArgs(args);
final StreamExecutionEnvironment env =
StreamExecutionEnvironment.getExecutionEnvironment();
env.getConfig().setGlobalJobParameters(parameters);
and then this should work
#Override
public void open(Configuration parameters) throws Exception {
ParameterTool params = (ParameterTool)
getRuntimeContext().getExecutionConfig().getGlobalJobParameters();
String jobName = params.get(nameOfParameterWithJobName);
}
The Configuration passed to open is always empty -- that's an obsolete mechanism that is no longer used. The method signature hasn't been changed in order to avoid breaking a public API.
Another good way to pass info like this to a RichFunction is to pass it to the constructor.

Problem with mocking - Null Pointer Exception when trying to mock external API method

I'm trying to test the class:
public class WeatherProvider {
private OWM owm;
public WeatherProvider(OWM owm) {
this.owm = owm;
}
public CurrentWeatherData getCurrentWeather(int cityId) throws APIException, UnknownHostException {
CurrentWeatherData currentWeather = new CurrentWeatherData(owm.currentWeatherByCityId(cityId));
return currentWeather;
}
public HourlyWeatherForecastData getHourlyWeather(int cityId) throws APIException, UnknownHostException {
HourlyWeatherForecastData hourlyWeather = new HourlyWeatherForecastData(owm.hourlyWeatherForecastByCityId(cityId));
return hourlyWeather;
}
}
OWM is an external API so I want to mock it. I wrote a test method:
#Test
void shouldReturnCurrentWeather() throws APIException, UnknownHostException {
//given
OWM owm = mock(OWM.class);
WeatherProvider weatherProvider = new WeatherProvider(owm);
int cityId = 123;
CurrentWeather currentWeather = WeatherDataStub.getCurrentWeather();
given(owm.currentWeatherByCityId(cityId)).willReturn(currentWeather);
//when
CurrentWeatherData currentWeatherData = weatherProvider.getCurrentWeather(cityId);
//then
}
I get a java.lang.NullPointerException in given().willReturn() line and I don't know why. I want to test cases when owm.currentWeatherByCityId(cityId) succesfuly returns CurrentWeather object (which is a stub class in this case) or throws exceptions.
Can you explain to me what I do wrong?

The constructor DefaultShardManagerBuilder() is deprecated (DefaultShardManagerBuilder builder = new DefaultShardManagerBuilder();)

What i do wrong?
It says me: The constructor DefaultShardManagerBuilder() is deprecated.
But Why and how can i Fix it (its my first code)
public class DonaldBot {
public ShardManager shardMan;
public static void main(String[] args) {
try {
new DonaldBot();
} catch (LoginException | IllegalArgumentException e) {
e.printStackTrace();
}
}
public DonaldBot() throws LoginException, IllegalArgumentException {
DefaultShardManagerBuilder builder = new DefaultShardManagerBuilder();
builder.setToken("NzUzNjI0NzU0MDI3NjI2NTg2.X1o5vw.1oT_Hhn6FVaZf8ewIHOkrTcEU-M");
builder.setActivity(Activity.watching("Chil Ecke"));
builder.setStatus(OnlineStatus.ONLINE);
builder.addEventListeners(new CommandListener());
this.shardMan = builder.build();
System.out.println("[Donald] Bot Online.");
According to the documentation, "Due to breaking changes to the discord api gateway you are now required to explicitly state which events your bot needs.". This answers the "why" part of your question.
Regarding the "how can I fix it", I'd try DefaultShardManagerBuilder builder = DefaultShardManagerBuilder.create(...).

Exceptions handler for getenv()

How can I handle NullPointerException and SecurityException for that kind of line code:
public final static String PROJECT_DIR = System.getenv().get("HOME") + "/Projects/MyTestProject";
It will be sufficient to just wrap it with try/catch? If so how I can differ it will be NullPointerException or SecurityException?
Also are there any best practices to have it stored in properties if getenv() is not available or something else?
Initialize the final static String in the class initializer. Throw a new exception describing the problem (not set, not allowed). For example:
public final static String PROJECT_DIR;
static {
try {
Map<String, String> env = System.getenv();
if (!env.contains("HOME")) {
throw new AssertionError("HOME not set as environment variable");
}
PROJECT_DIR = env.get("HOME") + "/Projects/MyTestProject";
} catch (SecurityException e) {
throw new AssertionError("Security policy doesn't allow access to system environment", e);
}
}
This would throw both NullPointerExceptions and SecurityExceptions:
public static void main(String[] args) throws Exception {
System.out.println("System.getenv("HOME") = ");
System.out.println(System.getenv("HOME"));

Some informations of how handle the main() args in Java [duplicate]

This question already has answers here:
How to make IntelliJ prompt me for command line arguments
(3 answers)
Closed 8 years ago.
I have to develop a command line Java application in which the main() method accept 2 String parameters named respetivelly partitaIVA and nomePDF.
So, as starting point, I created this simple Main class:
public class Main {
public static void main(String[] args) {
System.out.println("Hello World !!!");
}
}
I think that I can perform this minimalistic application from the Windows console and that I can perform my application passion these parameters to it doing something like this in the Windows console (or in the Linux shell):
java Main 123456789 myDocument.pdf
and I think that I can retrieve it inside my application modifying the original code in this way:
public class Main {
public static void main(String[] args) {
System.out.println("Hello World !!!");
String partitaIVA = args[0];
String nomePDF = args[1];
}
}
So now I have 2 doubts about this topic:
1) I know that I can perform this application specifying my 2 parameters using the Windows command line or the Linux shell but can I do the same thing into my IDE console? Specifically in the Run tab of IntelliJ?
2) Can I specify in some way that the parameters that the user can specify are only 2?
1) There is something called run/debug configuration https://www.jetbrains.com/idea/help/creating-and-editing-run-debug-configurations.html (here are also sone details about the specific options you have: https://www.jetbrains.com/idea/help/creating-and-editing-run-debug-configurations.html#d1628194e152)
2) No, you can only print an error and guide the user
You should invest the time in learning a modern CLI argument parser:
I prefer JewelCli
<dependency>
<groupId>com.lexicalscope.jewelcli</groupId>
<artifactId>jewelcli</artifactId>
<version>0.8.9</version>
</dependency>
Here is an example that can be used as a base class:
public class Main
{
private static final Logger LOG;
static
{
LOG = LoggerFactory.getLogger(Main.class);
}
private static Args init(#Nonnull final String[] args)
{
final Cli<Args> cli = CliFactory.createCli(Args.class);
try
{
return cli.parseArguments(args);
}
catch (final ArgumentValidationException e)
{
for (final ValidationFailure vf : e.getValidationFailures())
{
LOG.error(vf.getMessage());
}
LOG.info(cli.getHelpMessage());
System.exit(2); // Bash standard for arg parsing errors
return null; // This is to make the compiler happy!
}
}
private static List<String> parseKey(#Nonnull final String key)
{
return new ArrayList<String>(Arrays.asList(key.toLowerCase().split("\\.")));
}
#SuppressWarnings("unchecked")
private static Map<String, Object> addNode(#Nonnull Map<String, Object> node, #Nonnull final List<String> keys, #Nonnull final String value)
{
if (keys.isEmpty())
{
return node;
}
else if (keys.size() == 1)
{
node.put(keys.remove(0), value.trim());
return node;
}
else if (node.containsKey(keys.get(0)))
{
return addNode((Map<String, Object>) node.get(keys.remove(0)), keys, value);
}
else
{
final Map<String, Object> map = new HashMap<String, Object>();
node.put(keys.remove(0), map);
return addNode(map, keys, value);
}
}
public static void main(final String[] args)
{
try
{
final Args a = init(args);
final Properties p = new Properties();
p.load(new FileInputStream(a.getInputFile()));
final HashMap<String, Object> root = new HashMap<String, Object>();
for (final String key : p.stringPropertyNames())
{
addNode(root, parseKey(key), p.getProperty(key));
}
switch (a.getFormat().toLowerCase().charAt(0))
{
case 'j': LOG.info(mapToJson(root)); break;
case 'b' : LOG.info(Strings.bytesToHex(mapToCbor(root))); break;
case 'x' : LOG.error("XML not implemented at this time!"); break;
default : LOG.error("Invalid format {}", a.getFormat());
}
}
catch (IOException e)
{
throw new RuntimeException(e);
}
}
interface Args
{
#Option(shortName = "i", longName = "input", description = "Properties file to read from.")
File getInputFile();
#Option(shortName = "o", longName = "output", description = "JSON file to output to.")
File getOutputFile();
#Option(shortName = "f", longName = "format", description = "Format of output Json|Binary|Xml")
String getFormat();
#Option(helpRequest = true, description = "Display Help", shortName = "h")
boolean getHelp();
}
}
In Intellij (Linux) you do:
Press Alt + Shift + F10 (the run shortcut)
Press right key
Go down to Edit
Then press Tab to go to "Program arguments".
This is where you pass the arugments in IntelliJ. After that just hit run.

Categories

Resources