Load jobs at startup to Spring Batch Admin - spring-batch

From the Spring Batch Admin documentation, it mentioned that jobs will be loaded if job configuration file is located in classpath under META-INF/spring/batch/jobs/*.xml
Documentation
In the spring-batch-admin-sample that comes with STS, the jobs are loaded when the admin web application is deployed, under the file classpath:\META-INF\batch\module-context.xml And it is bootstrapped at deployment. Not sure how that works...
While I can load the job configuration by uploading in the user interface, http://localhost:8080/simple-batch-admin/configuration, some of my custom beans were not autowired for some reason. So the desirable behavior would be to load all the jobs when Admin is deployed.
Thank you in advance.

After several round of digging, I was able to load the job file. I have to place my job file in /META-INF/spring/batch/jobs/ folder not /META-INF/batch/ Also, in order for my jobLauncher, jobRepository, dataSource, etc. to get discover at load time. I have to put it in src/main/resources/META-INF/spring/batch/spring/batch/bootstrap/**/
All because of two files in spring-batch-admin-resources-1.2.0.RELEASE.jar in org.springframework.batch.admin.web.resources
servlet-config.xml
<import resource="classpath*:/META-INF/spring/batch/servlet/resources/*.xml" />
<import resource="classpath*:/META-INF/spring/batch/servlet/manager/*.xml" />
<import resource="classpath*:/META-INF/spring/batch/servlet/override/*.xml" />
which allows me to add menu and controller under the src/main/resources/META-INF/spring/batch/servlet/override/*xml
and
webapp-config.xml
<import resource="classpath*:/META-INF/spring/batch/bootstrap/**/*.xml" />
<import resource="classpath*:/META-INF/spring/batch/override/**/*.xml" />
where I put my launch context

Related

How to add the description of job in spring batch admin user interface?

Is there any way to add the description of job at the user interface of spring batch admin?
Although, I tried to added the description of the job, spring batch admin cannot support it.
I would like to know that whether spring batch admin does not support it or not.
I know i'm late to the party but I figured it out and it works flawlessly for me. All you have to do is :
Add a messages.properties file in your classpath (under
src/main/resources).
Add yourJobName.description=Your description goes here in that file.
Override manager-context.xml for SBA by creating a file on path src/main/resources/META-INF/spring/batch/servlet/override/manager-context.xml
The content of the above created file should be :
`
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<!-- Override messageSource bean in order to provide custom text content -->
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="messages" />
</bean>
</beans>
`
That's it. Your custom description shows up in SBA. Hope this helps someone who's looking for it.
There isn't the ability out of the box to display the job's description. That is only contained in the XML and the data seen in the UI comes from the JobRepository. You'd have to extend the UI to add that functionality.

How to process CASes produced by CAS Multiplier concurrently

I am implementing UIMA pipeline with CASMultiplier and UIMA AS. I have a Segmenter Analysis Engine (A CASMultiplier) and a Analysis Engine (Annotator A). I created a Aggregate Analysis Engine of the Segmenter and Annotator A, and then I create a UIMA AS Deployment descriptor file with intention, the Segmenter produces CASes, and then the Annotator A process with CASes concurrently. The contents of the aggregate analysis engine descriptor file and the deployment descriptor file are as following:
AAE descriptor file:
<analysisEngineDescription xmlns="http://uima.apache.org/resourceSpecifier">
<frameworkImplementation>org.apache.uima.java</frameworkImplementation>
<primitive>false</primitive>
<delegateAnalysisEngineSpecifiers>
<delegateAnalysisEngine key="Segmenter">
<import location="../cas_multiplier/SimpleTextSegmenter.xml"/>
</delegateAnalysisEngine>
<delegateAnalysisEngine key="AnnotatorA">
<import location="AnnotatorA.xml"/>
</delegateAnalysisEngine>
</delegateAnalysisEngineSpecifiers>
<analysisEngineMetaData>
<name>Segmenter and AnnotatorA</name>
<description>Splits a document into pieces and runs Annotator on each
piece independently. All segments are output.</description>
<configurationParameters/>
<configurationParameterSettings/>
<flowConstraints>
<fixedFlow>
<node>Segmenter</node>
<node>AnnotatorA</node>
</fixedFlow>
</flowConstraints>
<capabilities>
<capability>
<inputs/>
<outputs>
<type allAnnotatorFeatures="true">com.trang.uima.types.Target</type>
<type allAnnotatorFeatures="true">com.eg.uima.types.IntermediateResult</type>
</outputs>
<languagesSupported>
</languagesSupported>
</capability>
</capabilities>
<operationalProperties>
<modifiesCas>true</modifiesCas>
<multipleDeploymentAllowed>true</multipleDeploymentAllowed>
<outputsNewCASes>true</outputsNewCASes>
</operationalProperties>
</analysisEngineMetaData>
</analysisEngineDescription>
Deployment descriptor file:
<?xml version="1.0" encoding="UTF-8"?><analysisEngineDeploymentDescription xmlns="http://uima.apache.org/resourceSpecifier">
<name>SegmenterAndBackTranstion</name>
<description>Deploys Segmenter and BackTranskation with 3 instances of BackTransation</description>
<version/>
<vendor/>
<deployment protocol="jms" provider="activemq">
<casPool numberOfCASes="5" initialFsHeapSize="2000000"/>
<service>
<inputQueue endpoint="SegmentAnBackTranslationQueue" brokerURL="tcp://localhost:61616" prefetch="0"/>
<topDescriptor>
<import location="../../descriptors/langrid_uima/SegmenterAndBackTranslationAE.xml"/>
</topDescriptor>
<analysisEngine async="false">
<scaleout numberOfInstances="5"/>
<casMultiplier poolSize="8" initialFsHeapSize="2000000" processParentLast="false"/>
<asyncPrimitiveErrorConfiguration>
<processCasErrors thresholdCount="0" thresholdWindow="0" thresholdAction="terminate"/>
<collectionProcessCompleteErrors timeout="0" additionalErrorAction="terminate"/>
</asyncPrimitiveErrorConfiguration>
</analysisEngine>
</service>
</deployment>
</analysisEngineDeploymentDescription>
After have this setting, I run the pipeline, however, it seems the CASes are process synchronously, one at a time.
Could anyone tell me, what am doing wrong? Is there a way to process CASes produced by CASMultiplier concurrently?
Thank you very much!

IISExpress 8 with custom configuration file - web service won't load

When I develop a WCF service or website solution, I always use IISExpress with a custom configuration file so I can share the setup with other developers in the team. Basically, I run a batch file with the following command in it:
"C:\Program Files (x86)\IIS Express\iisexpress.exe" /config:service-hosts.config
Where service-hosts.config is the path to my custom configuration file.
This method has been working perfectly fine, and still works fine in other solutions on my PC (each with their own service-hosts.config file). However, I've just started having a problem loading a WCF service using this method. I'm getting the following error when trying to browse to the service root dir, or any of the built in help endpoints:
HTTP Error 500.19 - Internal Server Error
The requested page cannot be accessed because the related configuration data for the page is invalid.
Detailed Error Information:
Module IIS Web Core
Notification Unknown
Handler Not yet determined
Error Code 0x80070003
Config Error Cannot read configuration file
Config File \?\D:\Projects\MyProject\WCFSite\web.config
Requested URL http:// localhost:80/
Physical Path
Logon Method Not yet determined
Logon User Not yet determined
Request Tracing Directory C:\Users\Spikeh\Documents\IISExpress\TraceLogFiles\
Config Source:
-1:
0:
More Information:
This error occurs when there is a problem reading the configuration file for the Web server or Web application. In some cases, the event logs may contain more information about what caused this error.
If you see the text "There is a duplicate 'system.web.extensions/scripting/scriptResourceHandler' section defined", this error is because you are running a .NET Framework 3.5-based application in .NET Framework 4. If you are running WebMatrix, to resolve this problem, go to the Settings node to set the .NET Framework version to ".NET 2". You can also remove the extra sections from the web.config file.
View more information ยป
I've been debugging for hours and can't get this error to change, let alone fix it.
I've tried overwriting my service-hosts.config file with a few different versions of applicationHosts.config, running IISExspress in 64bit, replacing the web.config file with a very basic version, setting permissions on the directory (to the point where every user on my PC has access), and changing the app pool, but still no change.
The weird thing is... when I change the WCF project to use "IISExpress" in the Web section of project properties, then subsequently debug the project, everything works fine... even with all of my web.config settings in place.
This points to how I'm running IISExpress, or my service-hosts.config file... though the service-hosts.config file (with slight modifications for the sites involved) is exactly the same as it is in my other projects.
One thing to note (might be a red herring), but I did downgrade the solution from VS2012 to VS2010, and changed the framework target to .Net 4.0... not sure if something might be configured funny due to that?
Does anyone have any ideas? I'm at the point of jumping off the roof...
UPDATE:
Here's the debug information from IISExpress (running with /trace:e):
Running IIS...
Starting IIS Express ...
Initializing the W3 Server Started CTC = 5514916
PreInitSitesThread: Premature Exit Occured ( hr = 80070003 )
W3 Server initializing WinSock. CTC = 5514916
W3 Server WinSock initialized. CTC = 5514916
W3 Server ThreadPool initialized (ipm has signalled). CTC = 5514916
Start listenerChannel http:0
Successfully registered URL "http://*:80/" for site "MyWebsite" application "/"
Registration completed for site "MyWebsite"
AppPool 'MyCustomAppPool' initialized
InitComplete event signalled
IIS Express is running.
Enter 'Q' to stop IIS Express
IncrementMessages called
Request ended: http://localhost:80/ with HTTP status 500.19
And here's the important part of my service-hosts.config:
<applicationPools>
<add name="Clr4IntegratedAppPool" managedRuntimeVersion="v4.0" managedPipelineMode="Integrated" CLRConfigFile="%IIS_BIN%\config\templates\PersonalWebServer\aspnet.config" autoStart="true" />
<add name="Clr4ClassicAppPool" managedRuntimeVersion="v4.0" managedPipelineMode="Classic" CLRConfigFile="%IIS_BIN%\config\templates\PersonalWebServer\aspnet.config" autoStart="true" />
<add name="Clr2IntegratedAppPool" managedRuntimeVersion="v2.0" managedPipelineMode="Integrated" CLRConfigFile="%IIS_BIN%\config\templates\PersonalWebServer\aspnet.config" autoStart="true" />
<add name="Clr2ClassicAppPool" managedRuntimeVersion="v2.0" managedPipelineMode="Classic" CLRConfigFile="%IIS_BIN%\config\templates\PersonalWebServer\aspnet.config" autoStart="true" />
<add name="UnmanagedClassicAppPool" managedRuntimeVersion="" managedPipelineMode="Classic" autoStart="true" />
<add name="IISExpressAppPool" managedRuntimeVersion="v4.0" managedPipelineMode="Integrated" CLRConfigFile="%IIS_BIN%\config\templates\PersonalWebServer\aspnet.config" autoStart="true" />
<add name="MycustomAppPool" managedRuntimeVersion="v4.0" managedPipelineMode="Integrated" CLRConfigFile="%IIS_USER_HOME%\config\aspnet.config" autoStart="true" />
<applicationPoolDefaults managedRuntimeLoader="v4.0" >
<processModel/>
</applicationPoolDefaults>
</applicationPools>
<listenerAdapters>
<add name="http" />
</listenerAdapters>
<sites>
<site name="MyWebsite" id="1">
<application path="/" applicationPool="MyCustomAppPool">
<virtualDirectory path="/" physicalPath="D:\Projects\MyProject\WCFSite\" />
</application>
<bindings>
<binding protocol="http" bindingInformation="*:80:" />
</bindings>
</site>
<siteDefaults>
<logFile logFormat="W3C" directory="%IIS_USER_HOME%\Logs" />
<traceFailedRequestsLogging directory="%IIS_USER_HOME%\TraceLogFiles" enabled="true" maxLogFileSizeKB="1024" />
</siteDefaults>
<applicationDefaults applicationPool="Clr4IntegratedAppPool" />
<virtualDirectoryDefaults allowSubDirConfig="true" />
</sites>
<webLimits />
Seems that the service-hosts.config file was pointing to something it shouldn't have been pointing to. I replaced my service-hosts.config with an copy from an older project (and therefore an older version of IISExpress / .Net Framework) and everything works fine.
Sounds like it was to do with my 4.5 -> 4.0 downgrade after all.

Problem changing Database in Hibernate

i'm having a problem with hibernate and don't know exactly what's going on, i have this project at work where i connect to an Oracle 10g Database using the following settings:
Host Name: localhost
port:1521
SID:orcl
user:anfxi
password:password
Now i'm at home trying to work with the same database remotely, im connected via VPN and the database ip is now 10.73.98.230 , i imported my WAR and changed the settings in my
hibernate.cfg.xml from:
<property name="hibernate.connection.driver_class">oracle.jdbc.OracleDriver</property>
<property name="hibernate.connection.url">jdbc:oracle:thin://localhost:1521:orcl</property>
<property name="hibernate.connection.username">anfexi</property>
<property name="connection.password">password</property>
<property name="connection.pool_size">1</property>
<property name="hibernate.dialect">org.hibernate.dialect.OracleDialect</property>
<property name="show_sql">true</property>
<property name="hbm2ddl.auto">validate</property>
<property name="current_session_context_class">thread</property>
to:
<property name="hibernate.connection.driver_class">oracle.jdbc.OracleDriver</property>
<property name="hibernate.connection.url">jdbc:oracle:thin://10.73.98.230:1521:orcl</property>
<property name="hibernate.connection.username">anfexi</property>
<property name="connection.password">password</property>
<property name="connection.pool_size">1</property>
<property name="hibernate.dialect">org.hibernate.dialect.OracleDialect</property>
<property name="show_sql">true</property>
<property name="hbm2ddl.auto">validate</property>
<property name="current_session_context_class">thread</property>
but i keep getting this error:
ERROR [main] (SchemaValidator.java:135) - could not get database metadata
java.sql.SQLException: Listener refused the connection with the following error:
ORA-12505, TNS:listener does not currently know of SID given in connect descriptor
The Connection descriptor used by the client was:
localhost:1521:orcl
so it seems to be still using localhost as the DB address, i cleaned my project and rebuilt, still with no luck, is there something else that i could be missing? does the hibernate configuration gets cached in some file i have to erase or something?
EDIT
For what it may serve, i can connect using SQL developer,the problem is just hibernate still using the old localhost:1521:orcl Connection descriptor.
Thanks for your help!
Verify that the xml file you are changing in Eclipse is actually being deployed to the server. I run into problems every once in awhile where Eclipse doesn't know it needs to redeploy certain files for my webapp.
If you are using Tomcat and deploying using the workspace metadata (the default), you can check what the actual deployed WAR files look like by looking at your filesystem under:
WORKSPACE/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/APPNAME/.../path/to/hibernate.cfg.xml
If you find the config file is NOT being updated, I would recommend undeploying you app in Eclipse, deleting the entire APPNAME directory in the above path, and redeploying clean.
If none of that works, do a project-wide search for "localhost" and see if there could possible be any hardcoded connections strings anywhere.
This kind of problem is usually due to the wrong configuration file being present. Maybe you have two copies of the file and you changed one but the system is using the other
Typically when building/compiling, resources get copied to a target/build folder. Check source folders and build target folders etc.
Search the file system for all files with the name hibernate.cfg.xml or with the contents localhost:1521:orcl
Check the classpath, or try explicitly putting the folder with the configuration file you want first in the classpath.
It can also be a case of some other configuration overriding your configuration, for instance a datasource filer or a persistence.xml-file. Check those if you have them as well.
How are you running your application? Through a test case, standalone console application, servlet/j2ee container?
It is unable to understand the "orcl" SID. May be the SID is present on your "localhost" but not on the server "10.73.98.230". verify you are using the correct SID available on "10.73.98.230".
Try changing this line in your config file.
<property name="hibernate.connection.url">jdbc:oracle:thin:#10.73.98.230:1521:orcl</property>
replace // with #
you can follow the link the have infomation http://www.cryer.co.uk/brian/oracle/ORA12505.htm
Hope this will help

Correct way to make datasources/resources a deploy-time setting

I have a web-app that requires two settings:
A JDBC datasource
A string token
I desperately want to be able to deploy one .war to various different containers (jetty,tomcat,gf3 minimum) and configure these settings at application level within the container.
My code does this:
InitialContext ctx = new InitialContext();
Context envCtx = (javax.naming.Context) ctx.lookup("java:comp/env");
token = (String)envCtx.lookup("token");
ds = (DataSource)envCtx.lookup("jdbc/datasource")
Let's assume I've used the glassfish management interface to create two jdbc resources: jdbc/test-datasource and jdbc/live-datasource which connect to different copies of the same schema, on different servers, different credentials etc. Say I want to deploy this to glassfish with and point it at the test datasource, I might have this in my sun-web.xml:
...
<resource-ref>
<res-ref-name>jdbc/datasource</res-ref-name>
<jndi-name>jdbc/test-datasource</jndi-name>
</resource-ref>
...
but
sun-web.xml goes inside my war, right?
surely there must be a way to do this through the management interface
Am I even trying to do the right thing? Do other containers make this any easier? I'd be particularly interested in how jetty 7 handles this since I use it for development.
EDIT Tomcat has a reasonable way to do this:
Create $TOMCAT_HOME/conf/Catalina/localhost/webapp.xml with:
<?xml version="1.0" encoding="UTF-8"?>
<Context antiResourceLocking="false" privileged="true">
<!-- String resource -->
<Environment name="token" value="value of token" type="java.lang.String" override="false" />
<!-- Linking to a global resource -->
<ResourceLink name="jdbc/datasource1" global="jdbc/test" type="javax.sql.DataSource" />
<!-- Derby -->
<Resource name="jdbc/datasource2"
type="javax.sql.DataSource"
auth="Container"
driverClassName="org.apache.derby.jdbc.EmbeddedDataSource"
url="jdbc:derby:test;create=true"
/>
<!-- H2 -->
<Resource name="jdbc/datasource3"
type="javax.sql.DataSource"
auth="Container"
driverClassName="org.h2.jdbcx.JdbcDataSource"
url="jdbc:h2:~/test"
username="sa"
password=""
/>
</Context>
Note that override="false" means the opposite. It means that this setting can't be overriden by web.xml.
I like this approach because the file is part of the container configuration not the war, but it's not part of the global configuration; it's webapp specific.
I guess I expect a bit more from glassfish since it is supposed to have a full web admin interface, but I would be happy enough with something equivalent to the above.
For GF v3, you may want to try leveraging the --deploymentplan option of the deploy subcommand of asadmin. It is discussed on the man page for the deploy subcommand.
We had just this issue when migrating from Tomcat to Glassfish 3. Here is what works for us.
In the Glassfish admin console, configure datasources (JDBC connection pools and resources) for DEV/TEST/PROD/etc.
Record your deployment time parameters (in our case database connect info) in properties file. For example:
# Database connection properties
dev=jdbc/dbdev
test=jdbc/dbtest
prod=jdbc/dbprod
Each web app can load the same database properties file.
Lookup the JDBC resource as follows.
import java.sql.Connection;
import javax.sql.DataSource;
import java.sql.SQLException;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
/**
* #param resourceName the resource name of the connection pool (eg jdbc/dbdev)
* #return Connection a pooled connection from the data source
* associated with resourceName
* #throws NamingException will be thrown if resource name is not found
*/
public Connection getDatabaseConnection(String resourceName)
throws NamingException, SQLException {
Context initContext = new InitialContext();
DataSource pooledDataSource = (DataSource) initContext.lookup(resourceName);
return pooledDataSource.getConnection();
}
Note that this is not the usual two step process involving a look up using the naming context "java:comp/env." I have no idea if this works in application containers other than GF3, but in GF3 there is no need to add resource descriptors to web.xml when using the above approach.
I'm not sure to really understand the question/problem.
As an Application Component Provider, you declare the resource(s) required by your application in a standard way (container agnostic) in the web.xml.
At deployment time, the Application Deployer and Administrator is supposed to follow the instructions provided by the Application Component Provider to resolve external dependencies (amongst other things) for example by creating a datasource at the application server level and mapping its real JNDI name to the resource name used by the application through the use of an application server specific deployment descriptor (e.g. the sun-web.xml for GlassFish). Obviously, this is a container specific step and thus not covered by the Java EE specification.
Now, if you want to change the database an application is using, you'll have to either:
change the mapping in the application server deployment descriptor - or -
modify the configuration of the existing datasource to make it points on another database.
Having an admin interface doesn't really change anything. If I missed something, don't hesitate to let me know. And just in case, maybe have a look at this previous answer.