I'm trying to set an object into JNDI and then get remote access to it. I'm using TomEE 1.6.0. I'm setting a sinple string using an servlet like this:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,IOException
{
try
{
Context ctx=new InitialContext();
ctx.bind("myKey","MY STRING");
}
catch(NamingException ex)
{
ex.printStackTrace();
}
}
After running and invoke this servlet, I try to get remote access through JNDI using this standalone main.
public static void main(String[] args) throws Exception
{
Context ctx = getContext();
String nom = (String)ctx.lookup("java:/comp/env/nombre");
System.out.println(nom);
}
private static Context getContext() throws Exception
{
Hashtable<String,String> t = new Hashtable<>();
t.put("java.naming.factory.initial","org.apache.openejb.client.RemoteInitialContextFactory");
t.put("java.naming.provider.url","http://127.0.0.1:8080/tomee/ejb");
return new InitialContext(t);
}
But it throws an NameNotFoundException like this:
Exception in thread "main" javax.naming.NameNotFoundException: /comp/env/nombre does not exist in the system. Check that the app was successfully deployed.
at org.apache.openejb.client.JNDIContext.lookup(JNDIContext.java:319)
at javax.naming.InitialContext.lookup(InitialContext.java:411)
at demo.TestJNDI.main(TestJNDI.java:13)
So, my question are two:
1 - How can I know the default JNDI name which is using TomEE to publish this string?
2 - How can I set this string into any XML file instead the servlet?
Thanks!
Not sure what you expect to do but remote context is mainly an ejb/resource one. comp/env is clearly local to the application
Related
I am trying to override java.util.logging.LogManager with my own configuration:
class CloudwatchHandler is an implementation of Handler and includes this init() method:
public static void init() {
final String julConfigFile = System.getProperty("java.util.logging.config.file");
if(julConfigFile != null) {
try (InputStream is = new FileInputStream(julConfigFile)) {
LogManager logManager = LogManager.getLogManager();
logManager.reset();
logManager.readConfiguration(is);
Logger logger = Logger.getLogger(CloudwatchHandler.class.getName());
logger.info("LOADED");
} catch (SecurityException | IOException e) {
System.err.println(Instant.now() + ": Failed to initialize JUL.");
e.printStackTrace(System.err);
throw new RuntimeException(e);
}
}
else {
System.err.println(Instant.now() + ": java.util.logging.config.file was not specified");
}
}
Application main class
public static void main(String[] args) {
CloudwatchHandler.init();
SpringApplication.run(MyApp.class, args);
}
Error
Can't load log handler "mypackage.CloudwatchHandler"
java.lang.ClassNotFoundException: mypackage.CloudwatchHandler
java.lang.ClassNotFoundException: mypackage.CloudwatchHandler
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
at java.logging/java.util.logging.LogManager.createLoggerHandlers(LogManager.java:1005)
at java.logging/java.util.logging.LogManager$4.run(LogManager.java:975)
at java.logging/java.util.logging.LogManager$4.run(LogManager.java:971)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:318)
at java.logging/java.util.logging.LogManager.loadLoggerHandlers(LogManager.java:971)
at java.logging/java.util.logging.LogManager.initializeGlobalHandlers(LogManager.java:2424)
at java.logging/java.util.logging.LogManager$RootLogger.accessCheckedHandlers(LogManager.java:2526)
at java.logging/java.util.logging.Logger.getHandlers(Logger.java:2090)
at java.logging/java.util.logging.Logger.log(Logger.java:977)
at java.logging/java.util.logging.Logger.doLog(Logger.java:1007)
at java.logging/java.util.logging.Logger.log(Logger.java:1030)
at java.logging/java.util.logging.Logger.info(Logger.java:1803)
at mypackage.CloudwatchHandler.init(CloudwatchHandler.java:51)
... main ...
The really crazy thing about this exception is that the class causing the ClassNotFoundException is actually a caller in the current stack frame, as seen in the stack trace. So clearly it has been FOUND or it couldn't be running.
What's causing this and how can I fix it? I just want to load my own log handler.
Spring Boot version is 2.6.3.
ClassNotFoundException can occur if the Handler is not deployed to load in the system class loader as that is what the LogManager uses to find handlers.
Update your test case and try again:
public static void main(String[] args) throws Exception {
System.out.println(ClassLoader.getSystemClassLoader());
System.out.println(Thread.currentThread().getContextClassLoader());
System.out.println(CloudwatchHandler.class.getClassLoader());
//This is what CloudwatchHandler.init(); triggers
Class.forName(CloudwatchHandler.class.getName(), true, Thread.currentThread().getContextClassLoader());
//This is what the LogManager is doing
Class.forName(CloudwatchHandler.class.getName(), true, ClassLoader.getSystemClassLoader());
//Force load the root handlers.
Logger.getLogger("").getHandlers();
CloudwatchHandler.init();
SpringApplication.run(MyApp.class, args);
}
If it is that the handler is deployed in the context class loader and not in the system classloader then you need to change how you package the handler so it is visible to the system classloader. The java.util.logging.config.class option is one part of the LogManager that will try loading classes via context classloader which is what will be able to see your classes. For this option you move the contents of your init method to a new class and have the constructor perform the action. On the command line then set the value to the FQCN of the new config class.
Is there any reference guide for spring boot admin upgrade?
I have a legacy app that I need to upgrade from 1.5 to 2.0, but the entire API has changed & there is 0 info in the official reference guide. https://codecentric.github.io/spring-boot-admin/current/
For example, the main domain class now seems to be InstanceEvent, whereas it used to be 'Application'; but they hold completely different info.
Same with the class 'AbstractStatusChangeNotifier'; which now seems to use InstanceEvent & Spring webflux...
My more specific question is:
How can I get application info from spring boot admin 2.0?
I used to be able to do this; which now no longer exists in the api.
public class XXXMailNotifier extends AbstractStatusChangeNotifier {
#Override
protected void doNotify(ClientApplicationEvent event) {
try {
helper.setText(mailContentGenerator.statusChange(event), true);
} catch (IOException | MessagingException e) {
logger.error(e.getMessage());
}
}
String statusChange(ClientApplicationEvent event) throws IOException {
ImmutableMap.Builder<String, Object> content = ImmutableMap.<String, Object>builder()
.put("name", event.getApplication().getName())
.put("id", event.getApplication().getId())
.put("healthUrl", event.getApplication().getHealthUrl())
.put("managementUrl", event.getApplication().getManagementUrl())
.put("serviceUrl", event.getApplication().getServiceUrl())
.put("timestamp", DATE_TIME_FORMATTER.print(new LocalDateTime(event.getApplication().getInfo().getTimestamp())));
Well, if it might help anyone...
I looked in the code and found that I can get the info from the instance.registration object.
You can change the above in the below:
#Override
protected Mono<Void> doNotify(InstanceEvent event, Instance instance) {
try {
MimeMessage message = sender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setSubject(format(subject, environment, pool, instance.getRegistration().getName(), event.getInstance().getValue()));
helper.setText(mailContentGenerator.statusChange(event, instance, getLastStatus(event.getInstance())), true);
public String statusChange(InstanceEvent event, Instance instance, String lastStatus) throws IOException {
Registration registration = instance.getRegistration();
ImmutableMap.Builder<String, Object> content = ImmutableMap.<String, Object>builder()
.put("name", registration.getName())
.put("id", instance.getId().getValue())
.put("healthUrl", registration.getHealthUrl())
.put("managementUrl", registration.getManagementUrl())
.put("serviceUrl", registration.getServiceUrl())
.put("timestamp", DATE_TIME_FORMATTER.print(new LocalDateTime(instance.getStatusTimestamp())));
I have a folder structure /data/reports on a file system, which contains all reports.
How can I configure a SpringBoot application to serve the contents of this file sytem.
Currently I have tried few options, but none working
#Configuration
#EnableWebMvc
public class AppConfig implements WebMvcConfigurer {
#Value(value = "${spring.resources.static-locations:#{null}}")
private String fileSystem;
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry
.addResourceHandler("/data/reports/**")
.addResourceLocations(fileSystem)
.setCachePeriod(3600)
.resourceChain(true)
.addResolver(new PathResourceResolver());
}
}
and in application.properties I have defined
spring.resources.static-locations=file:///data/reports
server.servlet.jsp.init-parameters.listings=true
But in both cases, when I try
http://host:port/application/data/reports
I'm getting 404
What am I missing ?
Based on the suggestions given, I realized that one mistake I'm doing is to access the reports via
http://host:port/application/data/reports
instead of
http://host:port/data/reports
if I use application in the request, those calls will go through RequestDispatcher and will try to find for a matching RequestMapping, which does not exist. I think I'm convinced so far.
But the problem I'm seeing now is, I'm getting SocketTimeoutException while trying to read from the resource listed in the URL. I had put some breakpoints in Spring source "ResourceHttpMessageConverter.java"
protected void writeContent(Resource resource, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException {
try {
InputStream in = resource.getInputStream(); //It is timing out here
try {
StreamUtils.copy(in, outputMessage.getBody());
}
catch (NullPointerException ex) {
// ignore, see SPR-13620
}
The resource is a small text file with 1 line "Hello World". Yet it is timing out.
The resource in the above class is a FileUrlResource opened on file:///c:/data/reports/sample.txt
On the other hand, I tried to read that resource as
File file = new File("c:/data/reports/sample.txt");
System.out.println(file.exists());
URL url = file.toURI().toURL();
URLConnection con = url.openConnection();
InputStream is = con.getInputStream(); //This works
Thanks
I have a JBoss 7.1.2 application server up and running and now I wanted to deploy a OSGi bundle in it which registers a servlet. (kind of Hello World, but via a servlet)
Probably it is possible to archive this via a WAB, but as in OSGi, I thought it should also work in a simple, non wab bundle.
I created a bundle with an Activator as follows:
snip..
public void start(BundleContext bundleContext) throws Exception {
ServiceReference<?> httpServiceReference = bundleContext.getServiceReference(HttpService.class.getName());
System.out.println("ref: " + httpServiceReference);
HttpService httpService = (HttpService) context.getService(httpServiceReference);
System.out.println(httpService.getClass().getName());
try {
httpService.registerServlet("testservlet", new MyServlet() , null, null);
} catch (Exception e) {
e.printStackTrace();
}
}
After deploying and starting the bundle, the httpServiceReference is null.
I think this is strange, because when I look at the felix web console, there actually is HtttpService available. (from pax-web)
Does anyone know why my reference could be null here?
Thanks!
I think you are making the classical OSGi mistake. In the start(BundleContext context) method you are obtaining the reference to HttpService assuming its already started. The OSGi container starts bundles in some order. If your application bundle starts before the bundle that registers HttpService you will get a null reference. I suspect that's what is going on. You might be better off using ServiceTracker instead.
public void start(BundleContext bundleContext) throws Exception {
ServiceTracker httpServiceTracker = new ServiceTracker(bundleContext, HttpService.class, new ServiceTrackerCustomizer() {
#Override
public Object addingService(ServiceReference srf) {
HttpService httpService = bundleContext.getService(srf);
try {
httpService.registerServlet("testservlet", new MyServlet() , null, null);
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void modifiedService(ServiceReference arg0, Object arg1) {
}
#Override
public void removedService(ServiceReference arg0, Object arg1) {
}
});
httpServiceTracker.open();
}
I have a WebSphere Portal server that houses portlets. The portlets make remote calls to ejbs running on WAS. Both the portal server and the WAS are running on the local machine. The WAS starts up properly, but on trying to start up the portal server, it throws the following error:
nested exception is: java.lang.NullPointerException at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:286)
On looking up the source in spring, I find the method definition:
public PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
InjectionMetadata metadata = findAutowiringMetadata(bean.getClass());
try {
metadata.injectMethods(bean, beanName, pvs);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Autowiring of methods failed", ex);
}
return pvs;
}
Since the error is in spring source code and not my code, how should I start debugging it?