Throwing IOException from main() in Lambda-expression [duplicate] - java

This question already has answers here:
How can I throw CHECKED exceptions from inside Java 8 lambdas/streams?
(18 answers)
Closed 4 years ago.
I have a task to "move" my throws Exception from main() to lambda-expression. That means that when exception occurs in Lambda, the program uses throws from main. The problem is that I can't create any other interface which could automatically do that, because my teacher said to use only interface from java.util.Function and I've been looking in the internet, but mostly there are answers like "create new interface".
public static void main(String[] args) throws IOException {
Function<String, List<String>> flines = (String x) -> {
Stream<String> streamString = Files.lines(Paths.get(x)); //Should throw Exception from main if IOException
List<String> tmp = streamString.collect(Collectors.toList());
return tmp;
};

You can only throw a unchecked exception as Function doesn't declare any checked exception in the signature of its functional interface.
So you can only explicitly throw a RuntimeException (and its subclasses) instances from the lambda body such as :
Function<String, List<String>> flines = (String x) -> {
try{
Stream<String> streamString = Files.lines(Paths.get(x));
List<String> tmp = streamString.collect(Collectors.toList());
return tmp;
}
catch (IOException e){
throw new RuntimeIOException(e);
}
};
But declaring throws IOException in the main() method is so helpless as it will never be thrown it but if you catch the runtime exception in the Function client and that then you re-throw a IOException. But that is a lot of things for almost nothing.

You can catch the IOException inside the lambda expression, wrap it in a RuntimeException, catch that exception in the main, extract the wrapped IOException and throw it:
public static void main(String[] args) throws IOException
{
Function<String, List<String>> flines = (String x) -> {
List<String> tmp = null;
try {
Stream<String> streamString = Files.lines(Paths.get(x));
tmp = streamString.collect(Collectors.toList());
} catch (IOException ioEx) {
throw new RuntimeException (ioEx);
}
return tmp;
};
try {
List<String> lines = flines.apply ("filename.txt");
}
catch (RuntimeException runEx) {
if (runEx.getCause () instanceof IOException) {
throw (IOException) runEx.getCause ();
}
}
}

Related

How to catch a null pointer exception [duplicate]

This question already has answers here:
Catching nullpointerexception in Java [closed]
(5 answers)
Closed 2 years ago.
I have the code below and I am trying to catch an exception and print out something if the file == null so it doesn't throw an exception but I am having problems solving this.
public class Controller {
private ImageWindow IW = new ImageWindow(this);
private Model M = new Model(this.IW);
private File file = null;
public void openImage() {
File file = IW.ChooseImageFile();
if (file != null) {
M.loadImage(file);
}
this.IW.setVisible(true);
}
public static void main(String[] args) throws IOException {
SwingUtilities.invokeLater(() -> new Controller());
}
}
Usually I would use a try/catch statement for exception management in Java. Reference
try {
Enter code here
} catch (NullPointerException npe) {
System.out.println(“Error Message”);
}

Unhandled exceptions thrown by a method does not prevent compilation

So I have these two methods in a class:
public String getConsumerKey() throws FileNotFoundException, IOException
{
String consumerKey;
consumerKey = getPropertyValueOrNull(getConfigPath(CONSUMERVALUESCONFIGNAME),"consumer_key");
return consumerKey;
}
private String getPropertyValueOrNull(String path, String key) throws FileNotFoundException, IOException
{
Properties prop = new Properties();
String value = null;
// load a properties file
prop.load(new FileInputStream(path));
value = prop.getProperty(key);
if ( value == null || value.isEmpty())
{
value = null;
}
return value;
}
And I call getCosumerKey() from the main method like this:
public static void main(String[] args)
{
try {
MyClass.getInstance().getConsumerKey();
} catch (IOException e) {
e.printStackTrace();
}
}
When I run this code, there is no problem except that I am getting a FileNotFoundExcpetion. When I tried to add a catch block to handle the FileNotFoundException, I got an error saying that the exception is already handled from the IOException catch block.
Isn't the compiler supposed to prevent me from running the code and why does not compiler let me handle the exception?

Why am I getting this compiler error (using enum as singleton)?

I have the following class, which encapsulates some test data. I need only one instance of it, so I create an enum.
public enum ErnstReuterPlatzBuildings {
INSTANCE; // Compiler error occurs here
private final Map<String, IBuilding> buildingsByIds;
ErnstReuterPlatzBuildings() throws ParserConfigurationException,
SAXException, XPathExpressionException, IOException {
this.buildingsByIds = composeBuildingsByIds(
getBuildings(ErnstReuterPlatzBuildings.class)
);
}
public Map<String, IBuilding> getBuildingsByIds() {
return buildingsByIds;
}
public static Document readErnstReuterPlatzData(final Class clazz)
throws ParserConfigurationException, SAXException, IOException {
final InputStream stream =
clazz.getClassLoader()
.getResourceAsStream("mc/ernstReuterPlatz/map.osm");
final DocumentBuilderFactory dbfac =
DocumentBuilderFactory.newInstance();
final DocumentBuilder docBuilder = dbfac.newDocumentBuilder();
return docBuilder.parse(stream);
}
private Map<String, IBuilding> composeBuildingsByIds(
final Set<IBuilding> buildings) {
final Map<String,IBuilding> buildingsByIds = new HashMap<>();
for (final IBuilding building : buildings) {
buildingsByIds.put(building.getWayId(), building);
}
return buildingsByIds;
}
private Set<IBuilding> getBuildings(final Class clazz)
throws ParserConfigurationException, SAXException, IOException,
XPathExpressionException {
final Document doc = readErnstReuterPlatzData(clazz);
final PointsReader pointsReader = new PointsReader(doc);
pointsReader.init();
final BuildingExtractor testObject =
new BuildingExtractor(pointsReader);
return testObject.extractBuildings(doc);
}
}
At the declaration of its only element, INSTANCE; I get the following compiler error in IntelliJ Idea:
Error:(22, 5) java: unreported exception javax.xml.parsers.ParserConfigurationException; must be caught or declared to be thrown
How can I fix it, given that it occurs at the line, where the element is defined, not a method?
How can I fix it, given that it occurs at the line, where the element is defined, not a method?
Under the hood Java creates an instance INSTANCE by calling the constructor. The code on the declaration line looks similar to this:
public static final INSTANCE = new ErnstReuterPlatzBuildings();
That's why the error is coming from that line.
As far as I know, there is no way to fix this by allowing the user to catch a checked exception, because INSTANCE is initialized in a context outside of any method call.
You can work around this issue by catching the exception yourself, and wrapping it in an unchecked RuntimeException of an appropriate type or even an ExceptionInInitializerError:
ErnstReuterPlatzBuildings() {
try {
this.buildingsByIds = composeBuildingsByIds(
getBuildings(ErnstReuterPlatzBuildings.class)
);
} catch (ParserConfigurationException pce) {
throw new ExceptionInInitializerError(pce);
} catch (SAXException sxe) {
throw new ExceptionInInitializerError(sxe);
} catch (XPathExpressionException xpe) {
throw new ExceptionInInitializerError(xpe);
} catch (IOException ioe) {
throw new ExceptionInInitializerError(ioe);
}
}

File writing in Robocode (Java)

Basically, I am trying to generate a log file in Robocode, but I am having issues as you cannot use try/catch in Robocode (as far as I am aware). I have done the following:
public void onBattleEnded(BattleEndedEvent e) throws IOException
{
writeToLog();
throw new IOException();
}
and
public void writeToLog() throws IOException
{
//Create a new RobocodeFileWriter.
RobocodeFileWriter fileWriter = new RobocodeFileWriter("./logs/test.txt");
for (String line : outputLog)
{
fileWriter.write(line);
fileWriter.write(System.getProperty("line.seperator"));
}
throw new IOException();
}
and am getting the following error at compile time:-
MyRobot.java:123: onBattleEnded(robocode.BattleEndedEvent) in ma001jh.MyRobot cannot implement onBattleEnded(robocode.BattleEndedEvent) in robocode.robotinterfaces.IBasicEvents2; overridden method does not throw java.io.IOException
public void onBattleEnded(BattleEndedEvent e) throws IOException
^
1 error
As you can see here, the interface doesn't declare any checked exceptions. So you can't throw one in your implementing class.
One way to solve this would be to implement your method like this:
public void onBattleEnded(BattleEndedEvent e)
{
writeToLog();
throw new RuntimeException(new IOException());
}
public void writeToLog()
{
//Create a new RobocodeFileWriter.
RobocodeFileWriter fileWriter = new RobocodeFileWriter("./logs/test.txt");
for (String line : outputLog)
{
fileWriter.write(line);
fileWriter.write(System.getProperty("line.seperator"));
}
throw new new RuntimeException(new IOException());
}
but I am having issues as you cannot use try/catch in Robocode (as far as I am aware)
Where did this assumption came from? I just because of your question here installed robocode (so it's your fault if I'll answer here less often in future), wrote my own robot and it can catch exceptions quite good:
try {
int i = 1/0;
}
catch(ArithmeticException ex) {
ex.printStackTrace();
}
And why are you throwing IOExceptions in your example?

Why is the main method not covered?

main method:
public static void main(String[] args) throws Exception
{
if (args.length != EXPECTED_NUMBER_OF_ARGUMENTS)
{
System.err.println("Usage - java XFRCompiler ConfigXML PackageXML XFR");
}
String configXML = args[0];
String packageXML = args[1];
String xfr = args[2];
AutoConfigCompiler compiler = new AutoConfigCompiler();
compiler.setConfigDocument(loadDocument(configXML));
compiler.setPackageInfoDoc(loadDocument(packageXML));
// compiler.setVisiblityDoc(loadDocument("VisibilityFilter.xml"));
compiler.compileModel(xfr);
}
private static Document loadDocument(String fileName) throws Exception
{
TXDOMParser parser = (TXDOMParser) ParserFactory.makeParser(TXDOMParser.class.getName());
InputSource source = new InputSource(new FileInputStream(fileName));
parser.parse(source);
return parser.getDocument();
}
testcase:
#Test
public void testCompileModel() throws Exception
{
// construct parameters
URL configFile = Thread.currentThread().getContextClassLoader().getResource("Ford_2008_Mustang_Config.xml");
URL packageFile = Thread.currentThread().getContextClassLoader().getResource("Ford_2008_Mustang_Package.xml");
File tmpFile = new File("Ford_2008_Mustang_tmp.xfr");
if(!tmpFile.exists()) {
tmpFile.createNewFile();
}
String[] args = new String[]{configFile.getPath(),packageFile.getPath(),tmpFile.getPath()};
try {
// test main method
XFRCompiler.main(args);
} catch (Exception e) {
assertTrue(true);
}
try {
// test args length is less than 3
XFRCompiler.main(new String[]{"",""});
} catch (Exception e) {
//ignore
}
tmpFile.delete();
}
Coverage outputs displayed as the lines from String configXML = args[0]; in main method
are not covered.
assertTrue(true); is a pointless no-op
Remove the try/catch around the call to XFRCompiler.main(args);, since all it does is swallow excpetions and make debugging harder; most likely you will then see an exception that tells you where the problem is.
There should be a call to fail() after the call to XFRCompiler.main(new String[]{"",""}); since you expect it to throw an exception
Put the two calls in separate test methods.
I'm worried about all those assertTrue(true). If there can't be an exception, then the assert is not necessary. If there is an unexpected exception, then this code will swallow it and you will get the behavior you see right now.
Then, if you expect an exception, you should code like this:
try {
... code that will throw an exception ...
fail("No exception was thrown");
} catch (SpecficTypeOfException e) {
assertEquals("message", e.getMessage());
}
That way, wrong types of exception and the exception message will be checked.
PS: Don't post questions with "urgent". We already help as fast as we can.

Categories