How to access beans from the applicationContext.xml in my service layer. - java

How to access beans from the applicationContext.xml in my service layer.
I am working on a Spring Web MVC project and that issue is that my service layer needs a URL, User ID and Password to do a web post to a server to save my data. I dont want to hardcode the URL, User ID and password in the Java Code of the Service Layer so I would like to put them into the applicationContent.xml file but I dont know how to access them from the service layer.
Can someone please help me out with this.. example code would be great.

If your service is already a Spring managed bean, it should be trivial:
Add 3 properties to your service class (url, userId and password) along with their corresponding setters. Then you can set the values via your context:
<bean id="yourService" class="xxx.yyy.zz.YourService">
<property name="url" value="http://someurl.com"/>
<property name="userId" value="username"/>
<property name="password" value="passwd"/>
</bean>

Had a similar question. May be this link will be of help.
Spring MVC 3.0 - Service layer using annonations
Create a map of the values in dispatcher-servlet.xml and access it programmatically in your class. Or better inject the values to your bean in the xml file itself.
If you would rather have these values as environmental variables, that is also possible in Spring. Use a "propertyplaceholderconfigurer" for reading the external variables.
Let me know if you need further help.

Related

Spring data JPA - Do not hard code password in XML file

I am writing a Spring Jar (Without Spring boot) which connects to database. Almost all the tutorials which I saw connects to Database using the spring XML and the password is hard coded in the XML file.
This is in no way allowed in production environment and way out of standards in terms of security.
Can someone please help me if there is a way to inject password from a method call which inturn retrieves the password from a secured vault and provides the password to datasource object in runtime.
something like below.
<bean id="dataSource" class="org.springframework.jdbc.datasource.SingleConnectionDataSource">
<property name="driverClassName" value="org.postgresql.Driver" />
<property name="url" value="jdbc:postgresql://localhost:5432/postgres" />
<property name="username" value="postgres" />
<property name="password" value=getPasswordfromSecureVault("username") />
<property name="suppressClose" value="true" />
<jdbc:initialize-database >
<jdbc:script location="create-tables.sql"/>
</jdbc:initialize-database>
Based on the spring boot tag that you have, I'll assume that you're using spring boot for your project. With spring boot, it is very easy to externalize configuration for your application. It also auto-configures your datasource with a connection pool if you use the starters they provide.
In your case, you could benefit from moving to using spring boot's Externalized Configuration.
What that would allow you to do is to use an environment variable to configure your spring application. For example, to configure your password, use the environment variable SPRING_DATASOURCE_PASSWORD. You could also use the Java option -Dspring.datasource.password=[password] when starting the application, for example:
java -jar -Dspring.datasource.password=password app.jar
If using docker containers, the environment variable way is generally my go to as it's very straight forward for people to understand.
If you really want to configure the password from a method call, you can do that too using java configuration. Create a bean of type DataSource and Spring should pick it up and use it.
#Configuration
class AppConfiguration {
#Bean
public DataSource dataSource() {
String password = // Get your password
return DataSourceBuilder.create().password(password).build();
}
}

BridgePropertyPlaceholderConfigurer camel bean

I use the following bean to manage properties in camel as below :
<bean id="ilePropertiesConfigurer"
class="org.apache.camel.spring.spi.BridgePropertyPlaceholderConfigurer">
<property name="properties" ref="allProperties" />
</bean>
allproperties is a java class. it works very well when starting the application.
But now, I want to update properties without restarting my application. I update allproperties but it still takes the old values.
Can you help me?
This is not supported in Apache Camel with that Spring property placeholder bridge. You need to restart your application.
OSGi Blueprint has a concept of allowing to reload/restart your application when properties are changed, but it does a full bundle restart command.

Spring: display static page before context initialization to enter datasource password

I have a Spring 4.1.1 web application. Currently the datasource password is stored in a property file, in clear. Configuration is:
<bean id="mainDataSource"
class="com.mchange.v2.c3p0.ComboPooledDataSource"
scope="singleton"
destroy-method="close">
<property name="driverClass"><value>${jdbc.driver}</value></property>
<property name="jdbcUrl"><value>${jdbc.url}</value></property>
<property name="user"><value>${jdbc.username}</value></property>
<property name="password"><value>${jdbc.password}</value></property>
.
.
.
</bean>
My client doesn't want the password to be stored in a property file or, more in general, in the server.
The ideal would be to have Spring show a secure webpage to enter the database password.
The big problem is that I need access to the db to initialize the context and pretty much everything needed for the application to work. So the question is:
Is it possible to have Spring display a web page prior to context initialization, so that the user can enter the datasource password? Perhaps through a filter or something?
Please note to have the password encrypted in the property file or to have it passed as a parameter at Tomcat startup won't do, as it wouldn't be much different than having it in the property file, as regard to security.
What I ended up doing was to set the database password into an environment variable, use the variable inside the spring configuration files, and then delete the variable after startup. This worked and seems to make the client happy.
To read the environment variable in spring_db.xml us this expression, if you have Spring 3.0 and above:
<property name="password"><value>#{systemEnvironment['variable_name']}</value></property>

Dynamic Remote Service Location - How to inject with Spring?

I'm currently working on a distributed services architecture for a project at work. Essentially, we are managing upwards of 200 machines. Each of these machines has an instance of a service running on them that allows us to interface with the machine in a specific way.
At the center I have a control application which needs to talk to these 200 identical services. I was hoping to use RMI via Spring Remoting to make this happen, allowing me to #Autowire my remote service into my #Controller and treat it like a local service with exception propagation and maybe in the future propagation of transactions / security context via hooks.
This works great for a single service on a single machine where I can hardcode the remote service in my Spring configuration, but what I'm not able to figure out is how to dynamically choose which service (aka, which machine) I want to talk to at runtime and make that remote service available the "Spring" way.
I would like to be able to configure this dynamically from a database table and use the same table information to do a service lookup, while still taking advantage of dependency injection.
I thought of maybe injecting some kind of service manager that could do a service lookup of some sort, but was hoping someone else has managed to solve this (or a similar) problem elegantly.
An example of a hardcoded, single service instance would be like so:
The first XML snippet is on the machine service itself, telling Spring to expose it via RMI
<!-- Expose DeviceService via RMI -->
<bean class="org.springframework.remoting.rmi.RmiServiceExporter">
<property name="serviceName" value="DeviceService" />
<property name="service" ref="deviceService" />
<property name="serviceInterface"
value="com.example.service.DeviceService" />
<property name="registryPort" value="1199" />
</bean>
The second XML snippet is on the client (control application) which lets me access the exposed service
<!-- Proxy our remote DeviceService via RMI -->
<bean id="remoteDeviceService" class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
<property name="serviceUrl" value="rmi://machineurl:1199/DeviceService"/>
<property name="serviceInterface" value="com.example.service.DeviceService"/>
</bean>
It's that second bit of configuration that I'm trying to make dynamic. As you can see, to create this service proxy, I need to know at bean creation time the service URL. The Service URL can be 1 of 200+ variations, depending on what machine I want to talk to. The service I'm talking to is the same interface, but I won't know which machine until runtime depending on the current request context.
You could create connections to your servers dynamically with an additional service and remove "remoteDeviceService" from your client/controll app, i.e.:
public class RMIConnectionService {
public DeviceService connect(String serverUrl) {
RmiProxyFactoryBean factory = new RmiProxyFactoryBean();
factory.setServiceInterface(DeviceService.class);
factory.setServiceUrl("rmi://" + serverUrl + ":1099/SERVICE_URL");
factory.afterPropertiesSet();
//...
return (DeviceService) factory.getObject();
}
}
Then add this service to you service layer:
<bean id="rmiService" class="...RMIConnectionService" >
//...
</bean>
In your logic autowire the service and use it like:
DeviceService server1 = rmiService.connect("127.0.0.1");
For Database config add your DAO to this service, to load the right url. Port and url, or even the interface class could be configured this way too.
I have no RMI service to test this, but it worked with Hessian too. I hope this helps you.

Does Spring 3.0 provides a service definition file?

I'm wondering about Spring 3.0 whether it provides an automatically generated service definition page after I defined services.
With SOAP we have a WSDL file which contains WHAT, HOW and WHERE we can call a service.
Is that possible with Spring 3.0 or not?
Yes it does. Just add "?WSDL" to the URL of your Spring-generated web service and you'll get the definition. Also you can append "?xsd=1" instead and you'll get the schema you need (this is referenced also from the WSDL).
You can use an MBeanExporter to expose all of your services via JMX, which would be viewable through a JMX dashboard on your container (IE Tomcat, Jboss, etc). This is an easy way to account for 'what is deployed'. Your question is not entirely clear what sort of artifact you're looking for though.
<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
<property name="autodetect" value="true"/>
</bean>
Will automatically export all of your defined beans as MBeans. Usually that's not entirely what you want, so alternatively, you'll specify them manually.
<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
<property name="beans">
<map>
<entry key="bean:name=testBean1" value-ref="testBean"/>
</map>
</property>
</bean>
I agree with Chochos.
These[?wsdl, ?xsd=N] are universal standard to find the service definition file and any Datacontract defined in the wsdl.
example:
if http://localhost:8080/MyService is your service endpoint then it is service container's responsibility to make the WSDl available at http://localhost:8080/MyService,
by default.
The answer is Yes,
Use tag in your message dispatcher spring context file.
if your message dispatcher bean id is spring-ws then the spring context file for it would be spring-ws-servlet.xml.
In that context file,
import the namespace http://www.springframework.org/schema/web-services/web-services-2.0.xsd
xmlns:sws="http://www.springframework.org/schema/web-services".
then use the tag dynamic-wsdl from this namespace.
Also, you can set attributes for it like portType, binding and id. This will generate the wsdl file for you. You can view it by querying for it in the browser
/.wsdl

Categories

Resources