Log4J PropertyConfigurator migration to Log4J2 - java

I have the following legacy class which used PropertyConfigurator under Log4J 1.x
There's no equivalent under Log4J 2.x but I am trying to preserve the functionality at method level.
The existing answers on Stack Overflow are for locating the configuration file, but the legacy code I have in loadConfiguration is setting properties inside the configuration file about where the actual log file will be output.
I wish to know what the equivalent would be under Log4J2. It's not clear to me how the
loadConfiguration method will change due to not having a PropertyConfigurator under log4j 2.x.
Thanks in advance.
Existing code:
public class BasicLogConfigurator {
public static final String LOG_LEVEL_KEY = "log.level.override";
private static final Level DEFAULT_LOG_LEVEL = Level.ERROR;
private static final String LOG4J_PROPS_LOCATION = "/log4j.properties";
private static final String LOG_FILE_PATTERN = "CustomLog_%s.log";
private static final Date TIMESTAMP = new Date();
private static final String METADATA_FOLDER = ".metadata";
public static void loadDefaultConfiguration() {
// 1. Grab the Log file location
File logLocation = getLogFileLocationInMetadataDirectory();
// 2. Grab default Log level
Level logLevel = DEFAULT_LOG_LEVEL;
loadConfiguration(logLocation, logLevel);
}
public static void loadConfiguration(File logLocation, Level logLevel) {
Properties properties = getConfigurationProperties();
// 1. Setup the Log file location
properties.setProperty("log4j.appender.FILE.file", logLocation.getAbsolutePath());
// 2. Setup the default Log level
properties.setProperty("log4j.rootLogger", String.format("%s, CONSOLE, FILE", sanitizeLogLevel(logLevel)));
LogManager.resetConfiguration();
PropertyConfigurator.configure(properties);
}
public static File getLogFileLocationInMetadataDirectory() {
String workspaceDirectory = getWorkspaceDirectory();
File metadataDirectory = new File(workspaceDirectory, METADATA_FOLDER);
File logLocation = getLogFileLocation(metadataDirectory);
return logLocation;
}
public static File getLogFileLocation(File directory) {
return new File(directory, String.format(LOG_FILE_PATTERN, formatTimeStamp(TIMESTAMP)));
}
private BasicLogConfigurator() {
// prevent instantiation
}
private static Level sanitizeLogLevel(Level selectedLevel) {
String overridingLevel = System.getProperty(LOG_LEVEL_KEY);
if (overridingLevel != null) {
return Level.toLevel(overridingLevel, Level.DEBUG);
}
if (selectedLevel != null) {
return selectedLevel;
}
return DEFAULT_LOG_LEVEL;
}
public static String getWorkspaceDirectory() {
return ResourcesPlugin.getWorkspace().getRoot().getLocation().toOSString();
}
private static String formatTimeStamp(Date date) {
return new SimpleDateFormat("yyyyMMdd").format(date).toString();
}
public static Properties getConfigurationProperties() {
try {
Properties properties = new Properties();
properties.load(BasicLogConfigurator.class.getResourceAsStream(LOG4J_PROPS_LOCATION));
return properties;
} catch (IOException e) {
throw new RuntimeException(
String.format("Error while loading {%s}", LOG4J_PROPS_LOCATION), e);
}
}
}
So how is this done for Log4J2 given the inputs of the loadConfiguration method? And does getConfigurationProperties need to change to work with Log4J2?

Related

APPLICATION FAILED TO START when I try to work with mongoDB and SpringBoot

I have implemented a spring boot application to retrieve file data from files and save it in separate collections. When I run the application it gives the following error. I couldn't resolve it. Can anyone help me to do this?
Error
Description:
Parameter 2 of constructor in com.bezkoder.spring.jwt.mongodb.SpringBootSecurityJwtMongodbApplication required a bean of type 'com.bezkoder.spring.jwt.mongodb.models.LogRecordCollection' that could not be found.
Action:
Consider defining a bean of type 'com.bezkoder.spring.jwt.mongodb.models.LogRecordCollection' in your configuration.
Disconnected from the target VM, address: '127.0.0.1:55297', transport: 'socket'
LogRecordController.java
#CrossOrigin(origins = "*", maxAge = 3600)
#RestController
#RequestMapping("/api/auth/log")
public class LogRecordController {
#Autowired
LogRecordRepository logRecordRepository;
#GetMapping("")
public ResponseEntity<?> getAllLogRecordsByLogFileId(#RequestParam("fileId") String fileId) {
try{
LogRecordCollection logRecordCollection = new LogRecordCollection();
logRecordCollection.setCollectionName(fileId);
// List<LogRecord> logRecords = logRecordRepository.findAll(PageRequest.of(1, 10, Sort.by(Sort.Direction.ASC, "no"))).getContent();
List<LogRecord> logRecords = logRecordRepository.findAll();
return ResponseEntity.ok().body(logRecords);
}catch (Exception e){
return ResponseEntity.status(HttpStatus.EXPECTATION_FAILED).body(e.getMessage());
}
}
}
SpringBootSecurityJwtMongodbApplication.java
#SpringBootApplication
#CrossOrigin(origins = "*", maxAge = 3600)
#RestController
#RequestMapping("/api/auth/logFile")
public class SpringBootSecurityJwtMongodbApplication {
public SpringBootSecurityJwtMongodbApplication(LogFileRepository logfileRepo, LogRecordRepository logrecordRepo, LogRecordCollection logrecordColl) {
this.logfileRepo = logfileRepo;
this.logrecordRepo = logrecordRepo;
this.logrecordColl = logrecordColl;
}
public static void main(String[] args) {
SpringApplication.run(SpringBootSecurityJwtMongodbApplication.class, args);
}
#Bean
public ApplicationRunner runner(FTPConfiguration.GateFile gateFile) {
return args -> {
List<File> files = gateFile.mget(".");
for (File file : files) {
JSONArray arr = new JSONArray();
System.out.println("Result:" + file.getAbsolutePath());
run(file, arr);
}
};
}
void run(File file, JSONArray arr) throws IOException {
SimpleDateFormat formatter = new SimpleDateFormat("hh:mm:ss");
Pcap pcap = Pcap.openStream(file);
JSONObject obj = new JSONObject();
String fileName = file.getName();
pcap.loop(
packet -> {
String Time = null;
String Source = null;
String Destination = null;
String dataProtocol = null;
Long Length = null;
if (packet.hasProtocol(Protocol.TCP)) {
TCPPacket packet1 = (TCPPacket) packet.getPacket(Protocol.TCP);
Time = formatter.format(new Date(packet1.getArrivalTime() / 1000));
Source = packet1.getSourceIP();
Destination = packet1.getDestinationIP();
dataProtocol = packet1.getProtocol().toString();
Length = packet1.getTotalLength();
} else if (packet.hasProtocol(Protocol.UDP)) {
UDPPacket packet1 = (UDPPacket) packet.getPacket(Protocol.UDP);
Time = formatter.format(new Date(packet1.getArrivalTime() / 1000));
Source = packet1.getSourceIP();
Destination = packet1.getDestinationIP();
dataProtocol = packet1.getProtocol().toString();
Length = packet1.getTotalLength();
} else {
System.out.println("Not found protocol. | " + packet.getProtocol());
}
obj.put("Time", Time);
obj.put("Source", Source);
obj.put("Destination", Destination);
obj.put("Protocol", dataProtocol);
obj.put("Length", Length);
arr.add(obj);
return packet.getNextPacket() != null;
}
);
System.out.println(arr);
System.out.println(fileName);
Calendar calendar = Calendar.getInstance();
String now = String.valueOf(calendar.getTime());
LogFile data =logfileRepo.save(new LogFile("", fileName, now));
String collectionName = data.getFileName();
System.out.println(collectionName);
//Converting jsonData string into JSON object
//Creating an empty ArrayList of type Object
ArrayList<Object> listdata = new ArrayList<>();
//Checking whether the JSON array has some value or not
if (arr != null) {
//Iterating JSON array
for (int i=0;i<arr.size();i++){
//Adding each element of JSON array into ArrayList
listdata.add(arr.get(i));
}
}
logrecordColl.setCollectionName(collectionName);
listdata.addAll(logrecordRepo.findAll());
}
private final LogFileRepository logfileRepo;
private final LogRecordRepository logrecordRepo;
private final LogRecordCollection logrecordColl;
}
LogRecordRepository.java
import com.bezkoder.spring.jwt.mongodb.models.LogRecord;
import org.springframework.data.mongodb.repository.MongoRepository;
public interface LogRecordRepository extends MongoRepository<LogRecord, String>{
}
LogRecordCollection.java
public class LogRecordCollection {
private static String collectionName = "undefined";
public static String getCollectionName(){
return collectionName;
}
public void setCollectionName(String collectionName){
this.collectionName = collectionName;
}
}
Parameter 2 of constructor in com.bezkoder.spring.jwt.mongodb.SpringBootSecurityJwtMongodbApplication required a bean of type 'com.bezkoder.spring.jwt.mongodb.models.LogRecordCollection' that could not be found.
In an nutshell, the exception like this is self-explanatory. It means that Spring could not find a bean to be injected into your class
In your case the class SpringBootSecurityJwtMongodbApplication has a constructor:
public SpringBootSecurityJwtMongodbApplication(LogFileRepository logfileRepo, LogRecordRepository logrecordRepo, LogRecordCollection logrecordColl) {
this.logfileRepo = logfileRepo;
this.logrecordRepo = logrecordRepo;
this.logrecordColl = logrecordColl;
}
Now, LogRecordCollection has to be a bean (annotated with #Component for example, or defined in via java configuration (#Configuration marked classes and method annotated with #Bean that creates this class). Otherwise spring won't "recognize" this class a bean.
So strictly speaking this is your issue.
Now, having said that - the code you've presented in the question looks extremely messy - you mix #SpringBootApplication which is an entry point to the application, the rest controller and what not. I really recommend you to separate all this to different files to improve the code clarity and avoid unexpected exceptions that can be tricky to fix.
add below annotations in SpringBootSecurityJwtMongodbApplication
#SpringBootApplication
#ComponentScan("com.bezkoder.spring.jwt.mongodb") //to scan packages mentioned
#EnableMongoRepositories("com.bezkoder.spring.jwt.mongodb") //to activate MongoDB repositories
public class SpringBootSecurityJwtMongodbApplication { ... }

Relative path to file | Springboot

I am new to Spring-boot/Java and trying to read the contents of a file in a String.
What's the issue:
I'm getting "File not found exception" and unable to read the file. Apparently, I'm not giving the correct file path.
i've attached the directory structure and my code. I'm in FeedProcessor file and want to read feed_template.php (see image)
public static String readFileAsString( ) {
String text = "";
try {
// text = new String(Files.readAllBytes(Paths.get("/src/main/template/feed_template_head.php")));
text = new String(Files.readAllBytes(Paths.get("../../template/feed_template_head.php")));
} catch (IOException e) {
e.printStackTrace();
}
return text;
}
You need to put template folder inside resource folder. And then use following code.
#Configuration
public class ReadFile {
private static final String FILE_NAME =
"classpath:template/feed_template_head.php";
#Bean
public void initSegmentPerformanceReportRequestBean(
#Value(FILE_NAME) Resource resource,
ObjectMapper objectMapper) throws IOException {
new BufferedReader(resource.getInputStream()).lines()
.forEach(eachLine -> System.out.println(eachLine));
}
}
I suggest you to go though once Resource topic in spring.
https://docs.spring.io/spring/docs/3.0.x/spring-framework-reference/html/resources.html

Java - configure custom loggers for use

Trying to use java.util.logging and failing.
In an attempt to make use of https://stackoverflow.com/a/8249319/3322533 :
handlers = mypackage.logging.RequestFileHandler, mypackage.logging.MainFileHandler
config =
mainLogger.handlers = mypackage.logging.MainFileHandler
requestLogger.handlers = mypackage.logging.RequestFileHandler
java.util.logging.ConsoleHandler.level = INFO
java.util.logging.ConsoleHandler.filter =
java.util.logging.ConsoleHandler.formatter = mypackage.logging.VerySimpleFormatter
java.util.logging.ConsoleHandler.encoding =
mypackage.RequestFileHandler.level = SEVERE
mypackage.RequestFileHandler.filter =
mypackage.RequestFileHandler.formatter = mypackage.logging.VerySimpleFormatter
mypackage.RequestFileHandler.encoding =
mypackage.RequestFileHandler.limit =
mypackage.RequestFileHandler.count =
mypackage.RequestFileHandler.append = false
mypackage.RequestFileHandler.pattern = REQUESTS.%u.%g.log
mypackage.MainFileHandler.level = INFO
mypackage.MainFileHandler.filter =
mypackage.MainFileHandler.formatter = mypackage.logging.VerySimpleFormatter
mypackage.MainFileHandler.encoding =
mypackage.MainFileHandler.limit =
mypackage.MainFileHandler.count =
mypackage.MainFileHandler.append = false
mypackage.MainFileHandler.pattern = MAIN.%u.%g.log
where
public class MainFileHandler extends FileHandler {
public MainFileHandler() throws IOException, SecurityException {
super();
}
}
and
public class RequestFileHandler extends FileHandler {
public RequestFileHandler() throws IOException, SecurityException {
super();
}
}
Intention: provide two loggers accessible through
Logger.getLogger("mainLogger");
or
Logger.getLogger("requestLogger");
respectively, one that will write (exclusively) to MAIN[...].log and the other to REQUESTS[...].log
(No limits on the amount of messages that can be logged to either file and if necessary, use logging level to filter out unwanted msgs to either.)
However, neither file is created when I (for example)
public static final Logger log = Logger.getLogger("mainLogger");
and then
public void configureLogger(){
try {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream config = classLoader.getResourceAsStream("logging.properties");
LogManager.getLogManager().readConfiguration(config);
}catch(Exception ex){
throw new RuntimeException("logging properties failed");
}
}
before I
log.info("Hello World!")
I know the properties are loaded because when I include java.util.logging.ConsoleHandler in the handlers = ... list and use the global logger, instead, the formatter is applied for the console output.
So ... I guess my attempt at setting up the file loggers is faulty. How do I get this working?
EDIT
So I removed the [...].pattern = [...] lines and instead hardcoded the file names:
public class MainFileHandler extends FileHandler implements FileHandlerProperties {
public MainFileHandler() throws IOException, SecurityException {
super("MAIN_" + new SimpleDateFormat(TIME_PATTERN).format(new Date()) + ".log");
}
}
and
public class RequestFileHandler extends FileHandler implements FileHandlerProperties {
public RequestFileHandler() throws IOException, SecurityException {
super("REQUESTS_" + new SimpleDateFormat(TIME_PATTERN).format(new Date()) + ".log");
}
}
where
public interface FileHandlerProperties {
static final String TIME_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX";
}
Both files now get created BUT they both contain exactly the same (despite their different level settings and loggers) AND what they contain is in xml:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE log SYSTEM "logger.dtd">
<log>
<record>
<date>2016-10-10T18:49:23</date>
<millis>1476118163654</millis>
<sequence>0</sequence>
<logger>mainLogger</logger>
<level>INFO</level>
<class>mypackage.main.Main</class>
<method><init></method>
<thread>1</thread>
<message>Hello World</message>
</record>
</log>
Please help ...
The problem is that the first call to Logger.getLogger during class loading reads the log configuration and your configureLogger method fails due to JDK-8033661: readConfiguration does not cleanly reinitialize the logging system.
To workaround this you have to ensure that configureLogger runs before the first call to Logger.getLogger.
public class BootMain {
static {
configureLogger();
mainLogger = Logger.getLogger("mainLogger");
requestLogger = Logger.getLogger("requestLogger");
}
private static final Logger mainLogger;
private static final Logger requestLogger;
public static void main(String[] args) throws IOException {
mainLogger.log(Level.SEVERE, "Test from main.");
requestLogger.log(Level.SEVERE, "Test from request.");
System.out.println(new File(".").getCanonicalPath());
}
private static void configureLogger() {
try {
InputStream config = config();
LogManager.getLogManager().readConfiguration(config);
} catch (Exception ex) {
throw new RuntimeException("logging properties failed");
}
}
private static String prefix() {
return "mypackage.logging";
}
private static InputStream config() throws IOException {
String p = prefix();
Properties props = new Properties();
props.put("mainLogger.handlers", p + ".MainFileHandler");
props.put("requestLogger.handlers", p + ".RequestFileHandler");
props.put(p + ".RequestFileHandler.level", "SEVERE");
props.put(p + ".MainFileHandler.level", "INFO");
props.put(p + ".RequestFileHandler.pattern", "REQUESTS.%u.%g.log");
props.put(p + ".MainFileHandler.pattern", "MAIN.%u.%g.log");
ByteArrayOutputStream out = new ByteArrayOutputStream();
props.store(out, "");
return new ByteArrayInputStream(out.toByteArray());
}
}
Also make sure you are not using a really old version of JDK or you can run into JDK-5089480: java.util.logging.FileHandler uses hardcoded classname when reading properties.
Otherwise you can use the LogManager config option to manually setup your configuration.

Strange log4j declaration

I have a problem with an old project: The log file doesn't append in the console view of Eclipse. Instead of declaring the properties of log4j uses in log4j.xml or log4j.properties, the logger is defined in java:
import org.apache.log4j.FileAppender;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;
public class GCLogger {
private static GCLogger _self;
private Logger logger;
private static final String NAME_FILE = "fichierLog.log";
public static GCLogger getInstance() {
if (_self == null || _self.logger == null) {
GCLogger logger = new GCLogger();
logger.initLogger();
_self = logger;
}
return _self;
}
public void error(String msg, Exception e) {
if (logger != null) {
logger.error(msg, e);
}
}
public void debug(String msg) {
if (logger != null) {
logger.debug(msg);
}
}
private void initLogger() {
logger = Logger.getRootLogger();
FileAppender fa = new FileAppender();
PatternLayout monLayout = new PatternLayout("%d{DATE} - %5p %c{1} - %m%n");
logger.removeAllAppenders();
try {
File repLogs = new File(GCConstants.GC_REPERTOIRE_LOGS);
if (!repLogs.exists()) {
repLogs.mkdir();
}
fa = new FileAppender(monLayout, GCConstants.GC_REPERTOIRE_LOGS + File.separator + NAME_FILE, true);
fa.activateOptions();
fa.setImmediateFlush(true);
logger.addAppender(fa);
logger.setLevel(Level.ALL);
} catch(Exception e) {
logger = null;
}
}
}
Is there a simple way to show fichierLog.log in the console view (using eclipse configuration)?
If not, what is the minimal change to make it works?
Minimum change - add a console appender:
ConsoleAppender console = new ConsoleAppender(monLayout); // re-use the layout
logger.addAppender(console);
<opinion>
However, if you're making other changes to the codebase, I would strongly recommend changing this to use external configuration - it'll make your life much easier in the long (and probably short) term.</opinion>

NetBeans Platform: How to register hidden file types

I'm writing a NetBeans plugin and would like to register a file type. The file type is a hidden file (e.g. ".something") with mime-type text/plain and a settled name (".something"). The registration looks like this:
#MIMEResolver.ExtensionRegistration(
displayName = "#Label",
mimeType = "text/plain+something",
extension = {"something"}
)
#DataObject.Registration(
mimeType = "text/plain+something",
iconBase = "com/welovecoding/netbeans/plugin/logo.png",
displayName = "#Label",
position = 300
)
public class SomethingDataObject extends MultiDataObject {
public SomethingDataObject(FileObject pf, MultiFileLoader loader) throws DataObjectExistsException, IOException {
super(pf, loader);
registerEditor("text/plain", true);
}
//...
}
The problem with this is NetBeans will only recognize the filetype if the name of the file has a name, a point and an extension (e.g. "name.something"). Just a point and an extension (e.g. ".something") is not recognized properly. Is there a solution for this kind of problem?
I solved the problem by implementing a custom non-declarative MIMEResolver. Here's the code:
#ServiceProvider(service = MIMEResolver.class, position = 3214328)
public class FilenameResolver extends MIMEResolver {
private static final String mimetype = "text/plain+something";
public FilenameResolver() {
super(mimetype);
}
#Override
public String findMIMEType(FileObject fo) {
String nameExt = fo.getNameExt();
if (".something".equalsIgnoreCase(nameExt)) {
return mimetype;
}
return null;
}
}
There's a declarative MIMEResolver too. Note that the declarative way seems to be preferred by NetBeans-Devs.

Categories

Resources