spring boot multiple database configuration with microsoft sql server - javascript

i've multiple databases under a single sql server database.
from application.properties file. i've configured to default schema in springboot.
now i would like to chage to another database with same url, usrname, pawd.
how can i changedo this ? when i give annotation over class with
#table (name = db2.dbo.tname)
it throws error saying,
unable to map this dboject in database 1
here's my configuration:
spring.datasource.url=jdbc:sqlserver://localhost:1433;databaseName=testdb;integratedSecurity=false;
spring.datasource.username=sa
spring.datasource.password=myPassword
spring.datasource.driverClassName=com.microsoft.sqlserver.jdbc.SQLServerConnection
spring.datasource.initialize=true
my application works with the default db i gave on application properties. but i've to connect to another database.
how can i resolve this?

You cannot use the regular spring properties to do that. Here's an example on how you can connect to TWO databases (Or more if you need):
First you have to disable the autoconfiguration that picks up just one DB:
#EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class})
And now you just have to provide your own configuration for JPA and Datasources:
#Configuration
#EnableJpaRepositories(entityManagerFactoryRef = "ds1EntityManagerFactory",
transactionManagerRef = "ds1TransactionManager",
basePackageClasses = Ds1Repository.class)
public class DataSource1Config {
#Bean
PlatformTransactionManager ds1TransactionManager() {
return new JpaTransactionManager(tfccgEntityManagerFactory().getObject());
}
#Bean
LocalContainerEntityManagerFactoryBean ds1EntityManagerFactory() {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
factoryBean.setDataSource(ds1());
factoryBean.setJpaVendorAdapter(vendorAdapter);
factoryBean.setPackagesToScan(Ds1Entity.class.getPackage().getName());
factoryBean.getJpaPropertyMap().put("hibernate.dialect", dialect);
factoryBean.getJpaPropertyMap().put("hibernate.show_sql", showSQL);
factoryBean.getJpaPropertyMap().put("hibernate.globally_quoted_identifiers", quoteIdentifiers);
return factoryBean;
}
#Bean
DataSource ds1() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setUrl(url);
dataSource.setDriverClassName(driverClass);
dataSource.setUsername(username);
dataSource.setPassword(password);
dataSource.setTestOnBorrow(testOnBorrow);
dataSource.setMaxTotal(maxTotal);
dataSource.setInitialSize(initialSize);
dataSource.setMaxIdle(maxIdle);
return dataSource;
}
}
You can have a copy of this class for a ds2 datasource on which you'll have a second set of transactionManager entityManagerFactory and datasource and on which you'll enable JPA Repositories and Entity scan for different packages and name the beans with different names.
Then, If you need transaction isolation in a method you'll have to provide the transactionManager name since you'd have 2:
#Transactional(transactionManager = "ds1TransactionManager")

Related

How to make a ListView for a ChatApp to manage all chats?

I'm trying to create a List to manage all chats in my chat app. My chat app is using firebase. The problem is: Should I use a FlatList and save all data locally in a file or in a firebase database?
Save the data in firebase database. Saving data in a file is unprofessional as databases can handle larger data sets and can be much quicker when handling a large amount of data.
Use firebase for your chat app which can make everything simpler. For listview of firebase messages use this method
ListView listOfMessages = (ListView)findViewById(R.id.list_of_messages);
adapter = new FirebaseListAdapter<ChatMessage>(this, ChatMessage.class,
R.layout.message, FirebaseDatabase.getInstance().getReference()) {
#Override
protected void populateView(View v, ChatMessage model, int position) {
// Get references to the views of message.xml
TextView messageText = (TextView)v.findViewById(R.id.message_text);
TextView messageUser = (TextView)v.findViewById(R.id.message_user);
TextView messageTime = (TextView)v.findViewById(R.id.message_time);
// Set their text
messageText.setText(model.getMessageText());
messageUser.setText(model.getMessageUser());
// Format the date before showing it
messageTime.setText(DateFormat.format("dd-MM-yyyy (HH:mm:ss)",
model.getMessageTime()));
}
};
listOfMessages.setAdapter(adapter);
and for more query do visit this link :
enter link description here

Display a document without authentification

I am currently developping a java/jee application using alfresco as ged and spring as a framework.I want to display a file in the navigator without authentification requirment.So how can i do that.By the way i have 2 modules in my project:Frontend and backend which are communicating via rest calls.From the backend i tried to pass the byte array of the object but unfortunately i recieved it as string so i can't work with it.So any suggestion to solve this issue?
public Map<String, Object> getCourrierDetails(String idCourrier) throws Exception {
Map<String, Object> courriersDetails = runtimeService.getVariables(idCourrier);
courriersDetails.put("idCourrier", idCourrier);
DocumentDaoImpl dao=new DocumentDaoImpl();
Document docCmis = (Document) dao.getDocument("workspace://SpacesStore/73871a36-9a6c-42c6-b3e3-7d68362fe9c0");
byte[] myByteArray = readContent(docCmis.getContentStream().getStream());
ByteArrayResource resource = new ByteArrayResource(myByteArray) {
#Override
public String getFilename() {
return docCmis.getContentStreamFileName();
}
};
System.out.println(resource.getFilename());
//courriersDetails.put("resources", myByteArray);
System.out.println(courriersDetails.get("resources")+" rrrr");
//courriersDetails.put("contentStream",docCmis.getContentStream().getStream());
return courriersDetails;
}
Assuming your front-end and back-end are custom and your back-end communicates with Alfresco, all you need to do is write a proxy that resides in your back-end.
The proxy can establish a session with Alfresco using a pre-configured "service account" that has access to the content. In this way, the person using your custom webapp does not use their own credentials to get the object from Alfresco. Instead, the service account is used and the web app streams that to the requester.
For example, in one of my projects I have an AssetService that uses CMIS to get the InputStream from content given its ID:
public InputStream download(String assetId) {
CmisObject obj = session.getObject(assetId);
Document doc = null;
if (obj.getBaseTypeId().equals(BaseTypeId.CMIS_DOCUMENT)) {
doc = (Document) obj;
}
return doc.getContentStream().getStream();
}
Then, my Controller just asks the service for the asset to get some info about it to make it easy to set some helpful headers, then it gets the input stream from the asset service and returns that:
#RequestMapping(value = "/api/asset/{assetId:.+}/download/{name}", method = RequestMethod.GET)
public ResponseEntity<InputStreamResource> downloadAsset(
#PathVariable("assetId") String assetId,
#PathVariable("name") String name) {
// get the asset so we can get some info about it
Asset asset = assetService.getAsset(assetId);
// set the http headers (mimetype and length at a minimum)
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.parseMediaType(asset.getMimetype()));
httpHeaders.setContentLength(asset.getLength());
// get the content stream
InputStream inputStream = assetService.download(assetId);
InputStreamResource inputStreamResource = new InputStreamResource(inputStream);
return new ResponseEntity<InputStreamResource>(inputStreamResource, httpHeaders, HttpStatus.OK);
}
This example uses Spring MVC within a Spring Boot app but of course you could do something similar with a plain old servlet if you want.
One option is to write your own web script and set it up in a way that it allows guest access.
http://docs.alfresco.com/4.1/concepts/ws-authenticating.html
There's also an option to completely disable permission checking, which I have never tried, though.
https://community.alfresco.com/thread/175381-disabling-permission-checking

SignalR service: Get message depending on user role

I created
MVC app (installed -Install-Package Microsoft.AspNet.SignalR.JS) (ref here)
Web Service
(//Install from Nuget Package window
//Install-Package Microsoft ASP.NET SignalR .NET Client
//Install-Package Microsoft ASP.NET SignalR Core Components)
Signalr Service (Installed -Install-Package Microsoft.AspNet.SignalR.SelfHost and Install-Package Microsoft.Owin.Cors)
What I am doing: I am calling MVC page and after processing one task using web service. In that web service when task is processing I want to notify user what is going on behind the seen like task is in processing or it is done using Signalr service.
I created All project separately.
using web Service I am calling the signalr hubs (see here)
challenges facing:
I want to broadcast the message to that user and if no. of user are there then depending on there role i want to send messages.
Edited:Extra Enhancement added in my project:I have no. of MVC app and its corresponding Web services and My single signalR service so how can I identify which MVC app calling it corresponding service and service pushing to all or it application users or particular user. Like pusher will create application Id to application and number of tokens for user. It is possible to do it.
Summary:
I'm not sure that it's possible to have the hubs living on the WCF SignalR service. It would be best to let the MVC project act as a proxy between the client and web service. You can connect to SignalR later with other clients (such as desktop clients) if that's one of your requirements, and also connect to this hub from your web service to send updates to the clients and/or users in a specified group.
Workflow:
To start, the flow would look more like this:
Managing Client Connections:
If you are using an in-memory approach to managing your connected users, then you could start by adding the connection id and the user id to whatever collection you are using to handle this. For example:
public static ConcurrentDictionary<String, String> UsersOnline = new ConcurrentDictionary<String, String>();
public override System.Threading.Tasks.Task OnConnected()
{
UsersOnline.TryAdd(Context.ConnectionId, Context.User.Identity.GetUserId());
return base.OnConnected();
}
A word of caution: The Context.User will be null unless you map SignalR after the authentication.
It may be beneficial to store the connection id in variable on the client side as well so you can pass it to your methods later.
var connectionId;
var testHub = $.connection.testHub;
$.connection.hub.start().done(function () {
connectionId = $.connection.hub.id;
}
The Hub:
The hub can be used to communicate with the web service. In this example I'll be using it as a soap service, but rest should work just the same.
public void LongRunningTask(String ConnectionId)
{
using (var svc = new Services.MyWebService.SignalRTestServiceClient())
{
svc.LongRunningTask(ConnectionId);
} // end using
} // end LongRunningTask
Note that we pass the connection id to the service as well. This comes into play when the service starts sending messages back to the MVC project to deliver to the client(s).
Listener or Web API:
Set up a listener controller or a Web API on the MVC site to receive messages from the web service.
public ActionResult SignalR(String Message, String Type, String ConnectionId)
{
if (!String.IsNullOrWhiteSpace(Message) && !String.IsNullOrWhiteSpace(Type) && !String.IsNullOrWhiteSpace(ConnectionId))
{
if (Type == "ShowAlert")
{
// Determine if the user that started the process is still online
bool UserIsOnline = Hubs.TestHub.UsersOnline.ContainsKey(ConnectionId);
// We need this to execute our client methods
IHubContext TestHub = GlobalHost.ConnectionManager.GetHubContext<Hubs.TestHub>();
if (UserIsOnline)
{
// Show the alert to only the client that started the process.
TestHub.Clients.Client(ConnectionId).showAlert(Message);
} // end if
else
{
List<String> UserIdsInRole = new List<String>();
using (var connection = new System.Data.SqlClient.SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["DefaultConnection"].ToString()))
{
// Assuming you're using Identity framework since it is an MVC project, get all the ids for users in a given role.
// This is using Dapper
UserIdsInRole = connection.Query<String>(#"
SELECT ur.UserId
FROM AspNetUserRoles ur
JOIN AspNetRoles r ON ur.RoleId = r.Id
WHERE r.Name = #rolename
", new { rolename = "SpecialRole" }).ToList();
} // end using
// Find what users from that role are currently connected
List<String> ActiveUsersInRoleConnectionIds = Hubs.TestHub.UsersOnline.Where(x => UserIdsInRole.Contains(x.Value)).Select(y => y.Key).ToList();
// Send the message to the users in that role who are currently connected
TestHub.Clients.Clients(ActiveUsersInRoleConnectionIds).showAlert(Message);
} // end else (user is not online)
} // end if type show alert
} // end if nothing is null or whitespace
return new HttpStatusCodeResult(200);
} // end SignalR
Web Service:
The web service method that does the long running work should accept a client id as well, so it can send it back to the listener controller or web API. It can use a method similar to this (using RestSharp) to connect back to the MVC project:
public void ShowAlert(String Message, String ConnectionId)
{
RestClient Client = new RestClient("http://localhost:8888");
RestRequest Request = new RestRequest("/Listener/SignalR", Method.POST);
Request.Parameters.Add(new Parameter() { Name = "Message", Type = ParameterType.QueryString, Value = Message });
Request.Parameters.Add(new Parameter() { Name = "Type", Type = ParameterType.QueryString, Value = "ShowAlert" });
Request.Parameters.Add(new Parameter() { Name = "ConnectionId", Type = ParameterType.QueryString, Value = ConnectionId });
IRestResponse Response = Client.Execute(Request);
} // end Show Alert
Demo:
I did a proof of concept and uploaded it to Github.

Breeze js AutoGeneratedKeyType is always 'none' with ODataConventionModelBuilder

I have a simple entityframework poco object
public partial class Location: Entity
{
[Key]
public int Id { get; set; }
public string Description { get; set; }
}
The baseClass Entity looks as follow
public abstract class Entity : IObjectState
{
[NotMapped]
public ObjectState ObjectState { get; set; }
}
I expose this object via a Odata service using the ODataConventionModelBuilder
var server = GlobalConfiguration.DefaultServer;
ODataModelBuilder builder = new ODataConventionModelBuilder();
builder.Namespace = "MyNameSpace.Models";
builder.EntitySet<Location>(typeof(Location).Name);
var model = builder.GetEdmModel();
config.Routes.MapODataServiceRoute("odata", "odata", model, new DefaultODataBatchHandler(server));
config.AddODataQueryFilter();
When i consume this service with Breeze js i get an error from breeze when i try to create an entity with manager.CreateEntity().
Cannot attach an object to an EntityManager without first setting its
key or setting its entityType 'AutoGeneratedKeyType' property to
something other than 'None'
When i query an entity and edit the data and save it. All is ok.
I am using angular in combination with breeze on the client and Asp.net webapi 2 in combination with an odatacontroller on the server with EntityFramework 6 as ORM.
Can someone tell me what i am doing wrong!!!
Microsoft's ODataConventionModelBuilder is very incomplete, and they are aware of it ( This applies to both OData WebApi v 2.1 and v 2.2). Along with a number of smaller issues, it does not support 'referentialConstraints' or any info on store generated keys. MS is aware of these issues, among others, and has said that some of them will be fixed in a new release sometime in October.
Until then you have a couple of options.
Use the ODataConventionBuilder but then update breeze's metadataStore after the metadata is fetched to 'fix' the missing or wrong metadata.
myMetadataStore.metadataFetched.subscribe(function(args) {
var ms = args.metadataStore;
var entityType = ms.getEntityType("Customer");
entityType.setProperties({ autoGeneratedKeyType: AutoGeneratedKeyType.Identity });
dp = entityType.getDataProperty("companyName");
dp.validators.push(Validator.maxLength({ maxLength: 40 }));
// etc...
});
Avoid fetching metadata from the server at all and just describe the metadata on the breeze client directly: (see: http://www.breezejs.com/documentation/metadata-by-hand)
Skip OData completely and use the Breeze WebApi implementation (see http://www.breezejs.com/documentation/aspnet-web-api). This has the advantage of being both the most complete and the most robust implementation of all of breeze's features. Most of the Entity Framework samples in breeze.js.samples are built with this.
In general, we REALLY recommend the last choice if it is available to you. Please read this (http://www.breezejs.com/documentation/odata-server) for more information.

ASP.NET, EntityFramework - Send minimal data to client

I have a javascript application with ASP.NET MVC 3, SignalR and Entity Framework in the backend. I have always to prepare the data, because i dont want to send all attributes to the client (performance issue? e.g person has address has country has ... and this for > 1000 person entities). So, now i create always a prepare function before i send the data to the client:
public void GetPeople()
{
PersonRepository personRepository = new PersonRepository(_context);
var pList = personRepository.GetAll();
var pClientList = prepare(pList);
Clients[Context.ConnectionId].loadPeople(pClientList);
}
private object prepare(IEnumerable<Person> pList)
{
return from p in pList
select new
{
id = p.ID,
firstName = p.FirstName,
lastName = p.LastName,
displayName = p.DisplayName
};
}
and i dont think this is a good practice, because i have to create always for each entity an prepare function and on complex entities it gets weird.
You should use AutoMapper for this.
It also supports flattening for complex types, and it's very easy to implement and use.

Categories